float und double komisch ungenau !!
-
Hi,
hab gerade mal folgendes eingegeben:
float a=0.05f; double b=0.05;
und hab dann debugged.
Nach der Ausführung bekomme ich im Debugger angezeigt:a=0.050000001
b=0.050000000000000003Wie jetzt das ? warum ist die letzte Ziffer nicht 0 ?
(math.h eingebunden)
Ich frage das, weil ein 0.03 = 0.029999999999 ist und mir irgendwie in die
Suppe spuckt. Was geht hier ab ? ein atof funktioniert übrigens auch sehr
komisch mit diesen ungenauen Werten was sehr schlecht für die Benutzereingabe ist.Um jeden Hinweiss dankbar, kann mit der Suche leider nichts entsprechendes finden.
Gruß
thenoname
-
Das Problem ist, dass 0,05 wahrscheinlich nicht genau dargestellt werden kann. Ich hab's jetzt nicht bis ins letzte Bit nachgerechnet, wird aber so sein. Nach IEEE wird ein double in 1 Bit Vorzeichen, 8 Bit Exponent(Bias 127) und 23 Bit Mantisse (Binär) kodiert. Dabei wird die Mantisse (binär) auf z.B. 1,1010... genormt, also immer 1,..., die 1 vor dem Komma wird dann weggelassen und nur die Nachkommastellen kodiert.
Bei 0,05 würde das so aussehen:Dezimal Binär 0,5 0,1 0,25 0,01 0,125 0,001 0,0625 0,0001 0,03125 0,00001 (passen) 0,015625 0,000001 (passen) ...
0.5, 0.25 und 0.125 kann man nicht nehmen, weil diese bereits die erste Nachkommastelle füllen, was bei 0.05 nicht sein darf. 0.0625 ist größer als 0.05, wird also auch ausgelassen, also beginnt man bei der nächsten und addiert so lange, wie das Ergebnis nicht größer wird also die Zahl, die man sucht. Hier erhält man für die beiden Potenzen (von oben, die passen):
0,000011
Normiert: 1,1 (Exponent -5)Kodiert also:
0|01111010|10000000000000000000000Wenn man nun zurückrechnet, dann holt man sich das Vorzeichen, das ist 0, also positiv, den Exponent, der ist hier als 122 kodiert, Bias ist 127, also 122-127=-5 und bei der Mantisse denkt man sich eine 1 davor, erhält also 1,1(binär).
Dann rechnet man:
1,1 * 2^(-5) = 0,000011 (binär) = 0,046875 (dezimal).Daher kommen die Unstimmigkeiten. Ich bin jetzt nur bis zur 6. Nachkommastelle (binär) gegangen, wenn man wirklich bis zur 23. geht, dann entstehen noch Überträge etc., die das Ergebnis dann ziemlich genau werden lassen, aber halt nicht 100%-ig.
Daher sollte man auch nie zwei doubles beispielsweise mit "==" vergleichen.
Bei Float weiß ich nicht genau, wie's kodiert wird, aber da gibt es aus ähnlichen Gründen Ungenauigkeiten.
-
Eine einfachere Grobprüfung: Die Zahl als (gekürzten) Bruch darstellen. Ist der Nenner eine Potenz von 2, passt's, sonst nicht.
0.05 = 1/20. Zwanzig ist keine Potenz von 2 -> passt nicht.
-
wen du es genau haben wilst must du eine DECIMAL klaße nutzen^^
PS was hat das mit WinAPI zu tun!
-
-
Danke erstmal für die vielen Antworten,
das mit der Klasse DECIMAL probier ich doch gleich mal aus.strummelbunzi schrieb:
PS was hat das mit WinAPI zu tun!
-> hatte leider keine Ahnung wohin damit
Hat die Klasse DECIMAL auch sowas wie atof ?
Damit ich meine Editboxen übergeben kann ?Mist, ich seh gerade das DECIMAL gar kein 0.05 nimmt ??
Habt ihr ein Beispiel dafür ?
-
Dieser Thread wurde von Moderator/in Jochen Kalmbach aus dem Forum WinAPI in das Forum ANSI C verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.