2012-08-31 53 views
2

我有一段代码,上面写着:添加长双打给出了C中的错误的答案++

std::cerr << val1 << " " << val2 << std::endl; 
val1 = val1 + val2; 
std::cerr << val1 << std::endl; 

两个VAL1和val2长一倍。

的问题来自于一个事实,即这样做的结果是:

-5.000000000000722771452063564190e-01 2.710505431213761085018632002175e-20 
-5.000000000000722771452063564190e-01 

这是没有意义的。看来val2没有被添加到val1中,但是,在val1的小数部分显然有足够的信息可以将val2添加到它。

我很难过,任何人有任何想法?

我使用GCC 4.2我相信。 G ++是否使用IEEE四倍精度格式?或者别的东西(比如80位扩展精度,这可以解释这个问题(尽管为什么会出现超过18个小数位?)

+1

和最新的'的实际价值val1'&'val2' ?? – perilbrain

+0

Obligatory Goldberg链接:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html –

+0

这是什么架构和操作系统运行? –

回答

4

嗯,我应该猜到了...它看起来像G + +上的long double以四位精度格式存储,但是使用80位扩展精度格式计算,所以它会给出很多数字,但只有一些数字被计算出来

5

如果你的val1和val2打印正确,那么输出是正确的: -

-5.000000000000722771452063564190e-01 = -5.000000000000722771452063564190 X e^(-1) //or 10^(-1) 

其中^ denotes to the power of

2.710505431213761085018632002175e-20 = -5.000000000000722771452063564190 X e^(-20) //or 10^(-20) 

..

Since val1 >> val2 
=> lim (val2/val1 -> 0) (lim is mathematical limit) .... eq (A) 

Consider y=val1+val2 
=> y= ((val1+val2)/val1)*val1 (rationalizing) 
=> y= {(val1/val1)+(val2/val1)} * val1 
=> y= {1+val2/val1}*val1 
=> y= {1+0}*val1 .........................................From eq (A) 
=> y= val1 

这就是为什么输出是-5.000000000000722771452063564190e-01(因为通过添加所产生的差落在出表示由二进制长双精度格式的范围内的)

+0

我认为'e-01'实际上意味着'* 10 ^(-01)'。 –

+0

@MatthieuM:它的确如此。对于匿名ymous另外,如果您注意到,四倍精度浮点中可用的精度位数是〜35个十进制数字(远大于两个数字之间的19个数量级差异),这意味着它们应该被添加。但是,正如我在我的回答中所提到的,在G ++中,long double是用扩展的精度数字(具有大约19位精度)计算的。此外,你应该检查你的数学......这没有多大意义(你除以零,在其他错误)。 –

相关问题