c ++浮点精度损失:3015/0.00025298219406977296

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位十进制数字,所以这样的计算不应该导致问题.

jco*_*der 15

您是否在程序中使用directx,因为这会导致浮点单元切换到单精度模式,除非您明确告诉它何时不创建设备并且会导致