Sig*_*erm 17 c++ double x86 floating-accuracy
问题.
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;
Run Code Online (Sandbox Code Playgroud)
计算结果(即"f")是11917835.000000000(((unsigned __int64)(&f))== 0x4166bb4160000000)虽然它应该是11917834.814763514(即((unsigned __int64)(&f))== 0x4166bb415a128aef).
即分数部分丢失.
不幸的是,我需要小数部分才能正确.
问题:
1)为什么会发生这种情况?
2)我该如何解决这个问题?
附加信息:
0)结果直接来自"监视"窗口(它没有打印,我没有忘记设置打印精度).我还提供了浮点变量的十六进制转储,所以我对计算结果非常肯定.
1)f = a/b的反汇编是:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
Run Code Online (Sandbox Code Playgroud)
2)f = 3015/0.00025298219406977296; 得到正确的结果(f == 11917834.814763514,((unsigned __int64)(&f))== 0x4166bb415a128aef),但看起来在这种情况下,结果只是在编译时计算:
fld qword ptr [__real@4166bb415a128aef (828EA0h)]
fstp qword ptr [f]
Run Code Online (Sandbox Code Playgroud)
那么,我该如何解决这个问题呢?
PS我发现了一个临时的解决方法(我只需要除法的一小部分,所以我现在只使用f = fmod(a/b)/ b),但我仍然想知道如何正确解决这个问题 - 双精度应该是16位十进制数字,所以这样的计算不应该导致问题.