0*(1/0-1)=-2147483648

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
computerkranker
Beiträge: 66
Registriert: 12.10.2004 21:21

0*(1/0-1)=-2147483648

Beitrag von computerkranker »

Ich hatte gerade einen Fehler in meinen Programm, weil ich vergessen hatte die Null abzufangen(untere Beispiel "a"). Klar sollte man das tun bei Div durch Null, aber das Ergebniss ist gerundet trotdem sehr verwirrend.
Eigentlich schon fast lustig das 0*irgendwas einen Wert ergibt. :mrgreen:

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
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Viel schlimmer ist, das der Debugger keine Fehlermeldung ausgibt. Da kann es doch passieren, das man mit diesen komischen Werten weiterrechnet.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
benny
Beiträge: 383
Registriert: 29.08.2004 09:18
Wohnort: Am Ende des www's
Kontaktdaten:

Beitrag von benny »

Tja, man sollte halt immer im Hinterkopf haben,daß das Rechnen mit floats
nicht immer 100%ig genau ist.

Denkt an folgenden Thread :

http://robsite.de/php/pureboard-archiv/ ... ght=#42421
So long,
benny!
.
nur t0te f1sche schw1mmen m1t dem str0m - 00100 !
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag von freedimension »

benny hat geschrieben:Tja, man sollte halt immer im Hinterkopf haben,daß das Rechnen mit floats
nicht immer 100%ig genau ist.
Naja, zumindest die 0 lässt sich sehr genau als Float darstellen und 0 * ungenau ist immer noch 0 ;)
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

freedimension hat geschrieben:Naja, zumindest die 0 lässt sich sehr genau als Float darstellen und 0 * ungenau ist immer noch 0 ;)
Nein nicht zwingend (wenn ich mich richtig errinnere). Besonders wenn mit den Ergebnis aus 1/0 gerechnet wird...

Floats kann damit teilweise rumhantieren. Sollte man in Hinterkopf haben...
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Ähh, die ergebnisse kann man begründen. Die ersten zwei sind sogenannte NaN (Not a Number) werte. Das dritte ist wohl einfach die bytewerte des floats in einen int teleportiert und das ganze aufgerundet eben.

Deshalb braucht man die c++ funktion isnan(). Danilo hat eine funktion geschrieben, allerdings funktioniert die nicht immer bei mir.
Danilo 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.
[EDIT] Mein problem habe ich mittels Variablenspeicher gelöst. Einfach mal die bytes aus den entsprechenden NaN werten peeken ;) .
[EDIT2] ;) nochwas: Debug Sqr(-1)
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
TheShadow
Beiträge: 84
Registriert: 10.09.2004 16:19

Beitrag von TheShadow »

1/0 ist gleich unendlich

und bei floats wird das durchaus ohne fehler akzeptiert - floats erlauben auch -0 und +0

ziemlich flexibel was?
Zuletzt geändert von TheShadow am 18.01.2005 19:50, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

ähnelt meiner Signatur: Ganz viel Null ist fast ein bißchen Eins
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Der Fehler läßt sich reduzieren auf:

Code: Alles auswählen

a.l = 0
x.f = 1/a
y.l = Round(x,0)

Debug x
Debug y
Round muss schließlich für jeden Wert x irgendwas zurückliefern.
Falls x = NaN ist, liefert Round wieder NaN, falls ein Float erwartet wird. Wenn aber eine Int erwartet wird, dann hat man sich wohl dafür entschieden $80000000 zurückzugeben, was sehr vernünftig ist, da man dann leichter auf den Fehler aufmerksam wird, als das bei Rückgabewert 0 der Fall wäre.
!UD2
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag von Deeem2031 »

Was mir grad auffällt, warum komm da...

Code: Alles auswählen

y.f = -2147483648
Debug y
... +2147483648.000000 raus?
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Antworten