【发布时间】:2011-02-01 18:53:41
【问题描述】:
问题。
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 (((unsigned __int64)(&f)) == 0x4166bb4160000000) 虽然它应该是 11917834.814763514 (即 ((unsigned __int64 )(&f)) == 0x4166bb415a128aef)。
IE。小数部分丢失。
不幸的是,我需要小数部分才能正确。
问题:
1) 为什么会这样?
2) 我该如何解决这个问题?
附加信息:
0) 结果是直接从“watch”窗口获取的(它没有打印,我没有忘记设置打印精度)。我还提供了浮点变量的十六进制转储,所以我对计算结果非常肯定。
1)f = a/b的反汇编为:
fld qword ptr [a]
fdiv qword ptr [b]
fstp qword ptr [f]
2) f = 3015/0.00025298219406977296;产生正确的结果(f == 11917834.814763514 , ((unsigned __int64)(&f)) == 0x4166bb415a128aef ),但看起来在这种情况下结果只是在编译时计算:
fld qword ptr [__real@4166bb415a128aef (828EA0h)]
fstp qword ptr [f]
那么,我该如何解决这个问题呢?
附:我找到了一个临时解决方法(我只需要除法的小数部分,所以我现在只使用 f = fmod(a/b)/b),但我仍然想知道如何正确解决这个问题 - 双倍精度应该是 16 位十进制数字,所以这样的计算应该不会引起问题。
【问题讨论】:
标签: c++ x86 double floating-accuracy