Das Problem.C++ Fließkomma-Präzisionsverlust: 3015/0,00025298219406977296
Microsoft Visual C++ 2005-Compiler, 32-Bit-Windows XP sp3, und 64 x2 CPU.
Code:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
das Ergebnis der Berechnung (dh "f") ist 11.917.835,000000000 (((unsigned __int64) (& f)) == 0x4166bb4160000000), obwohl es 11.917.834,814763514 sein sollte (dh ((ohne Vorzeichen __int64) (& f)) == 0x4166bb415a128aef).
I.e. Bruchteil ist verloren.
Leider brauche ich Bruchteil, um richtig zu sein.
Fragen:
1) Warum passiert das?
2) Wie kann ich das Problem beheben?
Zusätzliche Informationen:
0) Das Ergebnis genommen wird direkt von „watch“ Fenster (es wurde nicht gedruckt, und ich habe nicht vergessen, den Druck Präzision eingestellt). Ich habe auch einen Hex-Dump der Gleitkommavariablen geliefert, also bin ich mir absolut sicher über das Berechnungsergebnis.
1), um die Demontage von f = a/b ist:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) f = 3015/0,00025298219406977296; korrektes Ergebnis Ausbeuten (f == 11.917.834,814763514, ((unsigned __int64) (& f)) == 0x4166bb415a128aef), aber es sieht aus wie in diesem Fall Ergebnis wird einfach während der Kompilierung Zeit berechnet:
fld qword ptr [[email protected] (828EA0h)]
fstp qword ptr [f]
So , wie kann ich dieses Problem beheben?
P.S. Ich habe einen temporären Workaround gefunden (ich brauche nur einen Bruchteil der Division, also verwende ich im Moment einfach f = fmod (a/b)/b), aber ich würde trotzdem gerne wissen, wie man dieses Problem richtig löst - doppelt Die Genauigkeit soll 16 Dezimalziffern entsprechen, daher sollte diese Berechnung keine Probleme verursachen.
Dies ist eine korrekte Antwort. Das Programm verwendet Direct3D, und natürlich erfolgt die Berechnung nach der Geräteerstellung. Das Lustige daran ist, dass ich wusste, dass D3D die FPU-Genauigkeit anpasst, aber ich habe es völlig vergessen, weil ich diesen Fehler in den letzten Jahren nicht gesehen habe. Problem gelöst. – SigTerm
Welches Flag sollte beim Erstellen des Geräts verwendet werden? Gibt es das gleiche Problem mit Direct2D? – dalle