Eigentlich schon fast lustig das 0*irgendwas einen Wert ergibt.

Code: Alles auswählen
a=0
z=0
f.f=z*(1/a-1)
d.l=Round(f.f,0)
Debug f.f
Debug Round(f.f,0)
Debug d.l
Code: Alles auswählen
a=0
z=0
f.f=z*(1/a-1)
d.l=Round(f.f,0)
Debug f.f
Debug Round(f.f,0)
Debug d.l
Nein nicht zwingend (wenn ich mich richtig errinnere). Besonders wenn mit den Ergebnis aus 1/0 gerechnet wird...freedimension hat geschrieben:Naja, zumindest die 0 lässt sich sehr genau als Float darstellen und 0 * ungenau ist immer noch 0
[EDIT] Mein problem habe ich mittels Variablenspeicher gelöst. Einfach mal die bytes aus den entsprechenden NaN werten peekenDanilo hat geschrieben:Als erstes mußt Du den Float-Wert mit FLD (Fpu LoaD) in das
Register ST(0) laden, danach kommt dann das FXAM.
FXAM setzt die Bits C0, C1, C2 und C3 im Status-Register
der FPU.
Im Status-Register (ein Word, also 16-Bit) findest Du diese
Bits wie folgt:
Code:
Bit 8 - C0-Flag
Bit 9 - C1-Flag
Bit 10 - C2-Flag
Bit 14 - C3-Flag
Das Status-Register kannst Du in eine 16-Bit-Speichervariable
laden, oder direkt ins CPU-Register AX: FSTSW AX
Nun hast Du den Status in AX und kannst die oben angegebenen
Bits auswerten. FXAM gibt dabei folgendes zurück:
Code:
| C0 | C2 | C3 |
-----+----+-----
| 0 | 0 | 0 | Nicht unterstützt
| 1 | 0 | 0 | NaN
| 0 | 1 | 0 | Normale endliche Zahl
| 1 | 1 | 0 | Unendlich
| 0 | 0 | 1 | Null
| 1 | 0 | 1 | Leer
| 0 | 1 | 1 | Denormalisierte Zahl
-----+----+-----
Im C1-Flag steht immer das Vorzeichen.
Deine Zahl in ST(0) mußt Du natürlich wieder entfernen.
Probier mal damit:
Code:
;
; by Danilo, 29.07.2004 - german forum
;
Procedure IsNaN(float.f)
; check float for NaN
; return: 1 = Not-a-Number
; 0 = no Not-a-Number
DisableDebugger
!FLD dword [esp]
!FXAM
!FSTSW AX
!FSTP dword [esp] ; !FFREE ST0
; !FINCSTP
!AND dword EAX,100h
!SHR dword EAX,8
ProcedureReturn
EnableDebugger
EndProcedure
Debug IsNaN( 0.0 )
Debug IsNaN( 2.0 )
Debug IsNaN( -99999999.9 )
Debug "-----"
a.f = 0.1
b.f = 0.0
Debug IsNaN( a / b )
Debug a / b
a = 99999999.9
b = 99999999.9
c.f = a*b*a*b*a*b
Debug Bin(IsNan( c ))
Debug c
PokeL(@a,$FFFFFFFF)
Debug IsNaN( a )
Debug a
Ich bin mir gerade etwas unsicher ob FFREE + FDECSTP
100%tig korrekt sind, wenn vorher noch andere Werte
auf dem Stack gespeichert wurden, deshalb der Kommentar
mit FSTP. Scheint aber so zu stimmen... icon7.gif
Im Moment gibt die Prozedur 1 zurück, wenn es eine NaN ist.
Das ist so wie bei Deiner ursprünglichen Prozedur.
Man kann aber auch noch die Zeile "!SHR dword EAX,8" weg-
lassen, dann gibt es immer $100 zurück wenn es eine NaN ist.
Der Check würde dann mit: If IsNaN( num.f ) trotzdem funktionieren.
Also 0 wenn es keine NaN ist und TRUE (d.h. alles ungleich 0)
wenn es eine NaN ist.
Wenn das so ist, dann musst Du die beiden Zeilen
Code:
!FFREE ST0 ;!FSTP dword [esp]
!FDECSTP ;
entfernen und durch das FSTP ersetzen. Deshalb hatte ich auch
beide Zeilen markiert, die gehören zusammen.
EDIT:
Ich seh grad des es FINCSTP statt FDECSTP sein müsste, dann dürfte
auch nichts durcheinander kommen. Da hat "Assembler gepackt" von
Joachim Rhode wieder mal einen Fehler, was es als Referenz
für mich langsam in Frage stellt. Hab da schon mehrere Fehler gefunden... icon_cry.gif
Mit dem FSTP geht es aber auf jedenfall korrekt, ich finds nur
blöd den Wert unnötigerweise wieder zurückzuschreiben.
Habe den obigen Code IsNaN() mal angepasst.
Code: Alles auswählen
a.l = 0
x.f = 1/a
y.l = Round(x,0)
Debug x
Debug y
Code: Alles auswählen
y.f = -2147483648
Debug y