这个问题。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