double mit 0 vergleichen
-
Hallo ihr,
ich habe mal eine Frage. Ich bin Student und habe mal vor längerer Zeit eine Programmieraufgabe abgegeben, wo ich eine Zahl vom Typ double mit 0 verglichen habe, also sowas wie (x==0). Als ich die Aufgabe abgegeben habe, hat mir der Korrektor irgendetwas davon erzählt, dass das Mist wäre und ich meine, er hätte vorgeschlagen, etwas in der Art |x|<epsilon mit einer kleinen Zahl epsilon zu checken (weiß ich aber nicht mehr genau). Damals war mir das ehrlich gesagt ziemlich egal, aber da ich jetzt wieder mal eine Programmieraufgabe mit Gleitkommazahlen habe, kam mir die Frage wieder in den Sinn und ich wollte es diesmal richtig machen. Allerdings verstehe ich gar nicht, warum x==0 falsch ist. Kann das jemand kurz erklären (oder ein Link zu einer Erklärung posten)?
Vielen Dank schonmal,
plizzz
-
x==0 ist nicht wirklich falsch. Du musst aber bedenken, dass eine double-Zahl mehr oder weniger beliebig nahe an 0 herankommen kann, z.B. könnte x==1.5e-245 sein, und das ist dann halt ungleich 0. Aufgrund der Rundungsfehler kommen solche kleinen Zahlen auch bei Rechnungen vor, bei denen man es gar nicht erwarten würde. Wenn du z.B. x=0.5 hast und dann 5mal 0.1 subtrahierst, kommt nicht 0 raus (sondern 2.7756e-017)
Deshalb gibt es die Faustregel, bei Fließkommazahlen nicht auf exakte Gleichheit zu testen, sondern den Abstand mit einem sinnvoll gewählten ε zu vergleichen.
-
Hallo,
es gibt zwei Gründe, warum man Doublevariablen nicht mit einer Konstanten vergleichen soll.
1. Auf Grund der internen Speicherung von Fließkommazahlen im Dualformat kann es passieren, daß eine Doublevariable genau diesen Wert gar nicht erreichen kann.
2. Auf Grund von Rundungsungenauigkeiten kann es passieren, daß ein Ausdruck für den Rechner gar nicht den gesuchten Wert erreicht, obwohl dies mathematisch der Fall wäre.Ich glaube (bin jetzt aber nicht sicher), daß die 0 zwar genau erreicht werden kann, Punkt 1 in Deinem Fall also keine Rolle spielt, Punkt 2 kann auf jeden Fall aber eintreten.
In einem Satz zusammengefaßt heißt dies:
Rundungsfehler können die Korrektheit Deiner Anwendung gefährden.mfg Martin
-
mgaeckler schrieb:
1. Auf Grund der internen Speicherung von Fließkommazahlen im Dualformat kann es passieren, daß eine Doublevariable genau diesen Wert gar nicht erreichen kann.
Das glaube ich nicht. Alle Fließkommakonstanten werden ja auch beim Parsen gerundet und als double bzw. float abgelegt. Wie soll sowas sonst auch auf Maschinenebene aussehen?
Ich glaube (bin jetzt aber nicht sicher), daß die 0 zwar genau erreicht werden kann
0 hat sogar zwei Repräsentationen, +0 und -0 (die allerdings als "gleich" gelten -- ziemlich pervers).
-
Bashar schrieb:
mgaeckler schrieb:
1. Auf Grund der internen Speicherung von Fließkommazahlen im Dualformat kann es passieren, daß eine Doublevariable genau diesen Wert gar nicht erreichen kann.
Das glaube ich nicht. Alle Fließkommakonstanten werden ja auch beim Parsen gerunden und als double bzw. float abgelegt. Wie soll sowas sonst auch auf Maschinenebene aussehen?
Ja klar, stimmt eigentlich. Da bin ich wohl über das Ziel hinausgeschossen.
Das Ergebnis bleibt aber das gleiche.
mfg Martin
-
Ah okay, das ergibt Sinn. Dankeschön!
-
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
http://docs.sun.com/source/806-3568/ncg_goldberg.html
-
Für die eigentliche Fragestellung nach Test auf 0 geht es auch anders ohne epsilon und Co:
int istDoubleNull(double d) { static double i; return !memcmp(&i,&d,sizeof i); }
-
Das kann man wohl kaum schlechter schreiben.