Problem.C++ Utrata dokładności zmiennoprzecinkowej: 3015/0,00025298219406977296
Kompilator Microsoft Visual C++ 2005, 32-bitowy system Windows XP sp3, AMD 64 x 2 procesor.
Kod:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
wynikiem obliczeń (czyli "F") jest 11917835,000000000 (((unsigned __int64) (& F)) == 0x4166bb4160000000), chociaż należy +11.917.834,814763514 (tj ((unsigned __int64) (& f)) == 0x4166bb415a128aef).
tj. część ułamkowa jest tracona.
Niestety, potrzebuję części ułamkowej, aby była poprawna.
Pytania:
1) Dlaczego tak się dzieje?
2) Jak mogę rozwiązać problem?
Dodatkowe informacje:
0) Wynik zostanie podjęta bezpośrednio z okna „watch” (nie został wydrukowany, i nie zapomnij ustawić precyzję drukowania). Dostarczyłem również zrzut heksowy zmiennej zmiennoprzecinkowej, więc jestem absolutnie pewien wyniku obliczeń.
1) demontaż f = a/b jest:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) F = 3015/0,00025298219406977296; Rentowności poprawny wynik (f == 11917834.814763514, ((unsigned __int64) (& f)) == 0x4166bb415a128aef), ale wygląda na to, w tym przypadku wynik jest po prostu obliczone podczas kompilacji:
fld qword ptr [[email protected] (828EA0h)]
fstp qword ptr [f]
So , jak mogę naprawić ten problem?
P.S. Znalazłem tymczasowe obejście (potrzebuję tylko częściowego podziału, więc używam po prostu f = fmod (a/b)/b w tej chwili), ale nadal chciałbym wiedzieć, jak rozwiązać ten problem poprawnie - podwójne precyzja ma być 16 cyfr dziesiętnych, więc takie obliczenia nie powinny powodować problemów.
To jest poprawna odpowiedź. Program używa Direct3D i oczywiście obliczenia odbywają się po utworzeniu urządzenia. Zabawne jest to, że wiedziałem, że D3D dostosowuje precyzję FPU, ale zupełnie o tym zapomniałem, ponieważ nie widziałem tego błędu w ciągu ostatnich kilku lat. Problem rozwiązany. – SigTerm
Jakiej flagi należy użyć podczas tworzenia urządzenia? Czy ten sam problem występuje z Direct2D? – dalle