double verhällt sich ungenau
-
Hallo,
wenn ich eine double wie folgt definiere:
double d = 3.2;
Dann befindet sich bei mir folgendes im Speicher: 3.2000000000000002
Das macht ja mal irgendwie überhaupt keinen Sinn? (Ich benutze VS2003 falls es daran liegen sollte?).
Bei einigen anderen Werten, z.B. 4.0 ist alles korrekt, also nur Nullen hinter der 4.
Ratlos ~fog
-
Es liegt nicht am Compiler, und es macht Sinn wenn man sich anschaut wie Fließkommazahlen dargestellt werden: http://de.wikipedia.org/wiki/IEEE_754
-
Das Problem ist grundsätzlicher Natur: double speichert seine Werte als Binärzahl in halblogarithmischer Darstellung - und da können einige Werte nicht exakt dargestellt werden (die werden dann entsprechend gerundet).
(versuch doch mal aus Spaß, die Zahl 3.2 in binärer Form hinzuschreiben - oder 1/3 exakt als Dezimalzahl darzustellen)
-
Das liegt daran, dass Zahlen im "Binärformat" gespeichert werden. Kann man auch nichts gegen machen, die Ungenauigkeit hast du immer drin. Wenn man float/double-Zahlen vergleicht, nimmt man sich idR ein kleines delta (z.B. 0,000001) und prüft, ob die Differenz der beiden zu Prüfenden kleiner als Delta ist, wenn ja, sind sie "gleich".
menno...
-
Ok,
Dann muss ich wohl die delta methode benutzen. Bekomme von einer Funktion 0.70000000000000007 zurück für 0.7 (warum auch immer), und wenn ich 0.7 selber definiere benutzt er 0.69999999999999996 wodurch der Vergleichsoperator verständlicherweise nicht glücklich ist.
Ist ja ganz schön umständlich jedes mal zwei Schranken definieren zu müssen mit denen man dann vergleichen kann.
Danke für die fixen und ausführlichen Antworten :-), hatte gar nicht an Binärdarstellung gedacht.
Grüße ~fog
-
das du "0.70000000000000007" zurueckbekommst ist doch normal:
Stichwort "Wertebereich"Bei PC-Systemen gilt im allgemeinen: Bitanzahl n Wertebereich Genauigkeit float 32 1.5E-45 .. 3.4E38 7- 8 Stellen double 64 5.0E-324 .. 1.7E308 15-16 Stellen long double 80 1.9E-4951 .. 1.1E4932 19-20 Stellen
mit der 7 bist du genau um eine stelle drueber, um genauer zu werden brauchst du dann long double