的问题。

的Microsoft Visual C ++编译器2005,32位的Windows XP SP3,AMD 64 X2处理器。

代码:

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(即((无符号__int64 )(&F))== 0x4166bb415a128aef)。结果 即小数部分丢失。结果 不幸的是,我需要小数部分是正确的。

问题:结果 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 [__real@4166bb415a128aef (828EA0h)]  
fstp        qword ptr [f]  

那么,如何才能解决这个问题呢?

P.S。我找到了一个临时的解决方法(我只需要分割的小数部分,所以我只是使用f = FMOD(A / B)的时刻/ B),但我还是想知道如何正确地解决这个问题 - 双精度被认为是16个十进制数字,所以这样的计算是不应该引起问题。

有帮助吗?

解决方案

您在你的程序的任何地方使用的DirectX作为使浮点单元即可切换为单精度模式,除非你明确告诉它不是在创建设备,并会造成正是这种

其他提示

有趣的是,如果你声明A和B作为花车,你会得到完全11917835.000000000。所以我的猜测是,有一个转换为单精度发生什么地方,无论是在怎样的常量解释或稍后在计算中。

这两种情况是有点出人意料,不过,考虑到你的代码是多么简单。您没有使用任何异国情调的编译器指令,迫使单精度所有浮点数字?

编辑:你有没有实际确认编译的程序产生不正确的结果?否则,对于(错误)单精度转换最可能的候选。将调试器。

如果你需要精确的数学,不使用浮动点。

请你帮个忙,并获得BIGNUM库有理数的支持。

我猜你打印出来的数字,没有指定的精度。尝试这样:

#include <iostream>
#include <iomanip>

int main() { 
    double a = 3015.0; 
    double b = 0.00025298219406977296;
    double f = a/b;

    std::cout << std::fixed << std::setprecision(15) << f << std::endl;
    return 0;
}

此产生:

11917834.814763514000000

这看起来是正确的给我。我使用VC ++ 2008,而不是2005年,但我猜想不同的是在你的代码,而不是编译器。

您确定您的FSTP指令后检查F的权值?如果你有开启或者监视窗口可以显示在以后的某个点取一个值优化(这似乎有点似是而非,你说你以后看f的小数部分 - 做一些指令风力可达掩盖它出某种方式?)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top