Seite 1 von 1
IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 24.07.2011 11:32
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
Re: IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 24.07.2011 13:45
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.
Re: IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 24.07.2011 14:45
von cxAlex
Ist gemacht, danke
Gruß, Alex
Re: IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 24.07.2011 15:04
von STARGÅTE
Danke, wie gesagt, ist eigentlich kleinkram, da Log() im vergleich dazu ewig braucht ^^
Re: IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 11.10.2011 16:41
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
Re: IsPowerOf2(), ld() (Logarithmus Dualis)
Verfasst: 14.10.2011 16:21
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