IsPowerOf2(), ld() (Logarithmus Dualis)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von cxAlex »

Mal ein ganz kleiner Code-Schnipsel, aber doch sehr praktisch (zumindest für mich im Moment). 2 Kleine Macros um den Logarithmus einer Zahl zur Basis 2 zu berechnen und ein Macro um zu Überprüfen ob eine Zahl eine Potenz von 2 ist. Ich brauche das gerade in meinem ByteCode-Compiler um Divisionen und Multiplikationen durch Potenzen von 2 automatisch durch Bit-Shift Befehle ersetzen zu können.

Wers braucht:

Code: Alles auswählen

; Zahl ist 2^x
Macro IsPowerOf2(_Value)
  ((_Value&(_Value-1))=#Null)
EndMacro

; Logarithmus zur basis 2 (binärlogarithmus, Logarithmus Dualis)
#_1dLN_2 = 1.4426950408889634074
Macro ld(x)
  (Log(x)*#_1dLN_2)
EndMacro
Gruß, Alex
Zuletzt geändert von cxAlex am 24.07.2011 14:45, insgesamt 1-mal geändert.
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von STARGÅTE »

Nur der Formhalber:
Log(x)/#_LN_2
ist zu "langsam", es wäre besser 1/Log(2) als Konstante festzulegen und dann zu multiplizieren.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von cxAlex »

Ist gemacht, danke :)

Gruß, Alex
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von STARGÅTE »

Danke, wie gesagt, ist eigentlich kleinkram, da Log() im vergleich dazu ewig braucht ^^
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von Helle »

Da ich Ld auch gerade mal brauchte:

Code: Alles auswählen

Procedure.d Ld(x.d)
  !fld1                 ;lade y=1
  !fld qword[p.v_x]     ;lade x
  !fyl2x                ;berechnet y mal Ld(x) 
 ProcedureReturn 
EndProcedure

MessageRequester("Logarithmus dualis", StrD(Ld(123.456), 15))
Die FPU-Instruction "fyl2x" berechnet den Ld von x und multipliziert den dann mit y. Wird y auf 1 gesetzt (mit fld1), kommt eben Ld(x) heraus.

Gruß
Helle
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Re: IsPowerOf2(), ld() (Logarithmus Dualis)

Beitrag von Helle »

Hier noch eine Version von IsPowerOf2:

Code: Alles auswählen

Procedure IsPowOf2(TestVal.d)                        ;der Testwert wird der Procedure als Double übergeben
  Double.q = PeekQ(@TestVal) & $7FFFFFFFFFFFFFFF      ;Vorzeichen-Bit ausblenden (Bit 63)
  Exp.q = Double >> 52                                ;Exponent = Bits 52 bis 62 (11 Bits)  
  Man.q = Double & $FFFFFFFFFFFFF                     ;Mantisse = Bits 0 bis 51 (52 Bits)
  If Man = $FFFFFFFFFFFFF                             ;also fast 1
    Man = 0                                           ;kann zu Null aufgerundet werden; ist ja Aufaddierung
    Res = 1                                           ;Exponent dafür um eins erhöhen    
  EndIf
  If Double = 0  Or Man <> 0 
    Res = #False                                      ;Null
   Else 
    Res + Exp + #True                                 ;Res mit Bias (1023 für Double), für #True evtl. besser 1
  EndIf  
 ProcedureReturn Res
EndProcedure

;Testwerte
Res = IsPowOf2(1.3079939052566739757e+297)
;Res = IsPowOf2(1025)
;Res = IsPowOf2(1024.000000000001)
;Res = IsPowOf2(1024.000000000000)
;Res = IsPowOf2(1)
;Res = IsPowOf2(0)
;Res = IsPowOf2(0.0625)

If Res
  Res$ = "Ja, der Exponent ist " + Str(Res - 1024)    ;1024 = Bias + 1 (#True)
 Else 
  Res$ = "Nein"
EndIf  

MessageRequester("Is Power of 2 ?", Res$)

Viel Spaß!
Helle
Antworten