這個問題。C++浮點精度損失:3015/0.00025298219406977296
Microsoft Visual C++ 2005編譯器,32位windows xp sp3,amd 64 x2 cpu。
代碼:
double a = 3015.0;
double b = 0.00025298219406977296;
//*((unsigned __int64*)(&a)) == 0x40a78e0000000000
//*((unsigned __int64*)(&b)) == 0x3f30945640000000
double f = a/b;//3015/0.00025298219406977296;
計算的結果(即 「F」)是11917835.000000000(((無符號__int64)(& F))== 0x4166bb4160000000)儘管它應該是11917834.814763514(即((unsigned __int64)(& f))== 0x4166bb415a128aef)。
I.e.小數部分丟失。
不幸的是,我需要小數部分是正確的。
問題:
1)爲什麼會發生這種情況?
2)我該如何解決這個問題?
附加信息:
0)的結果被直接從「手錶」窗口(這是不打印,我沒有忘記設置打印精度)。我也提供了浮點變量的十六進制轉儲,所以我對計算結果非常肯定。
1)F = A/B的拆卸是:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2)F = 3015/0.00025298219406977296;產生正確的結果(F == 11917834.814763514,((無符號__int64)(& F))== 0x4166bb415a128aef),但它看起來像在這種情況下,結果在編譯時簡單地計算:
fld qword ptr [[email protected] (828EA0h)]
fstp qword ptr [f]
所以,我該如何解決這個問題?
P.S.我找到了一個臨時解決方法(我只需要除法的小數部分,所以我現在簡單地使用f = fmod(a/b)/ b),但我仍然想知道如何正確解決這個問題 - double精度應該是十六進制數字,所以這樣的計算不應該導致問題。
這是一個正確的答案。程序使用Direct3D,當然,計算髮生在設備創建後。有趣的是,我知道D3D調整FPU精度,但我完全忘了它,因爲我在過去幾年沒有看到這個錯誤。 問題解決。 – SigTerm 2010-03-28 19:24:48
創建設備時應該使用哪個標誌? Direct2D存在同樣的問題嗎? – dalle 2010-08-04 16:22:19