2012-05-09 118 views
3

我发现了一个有趣的情况,其中相同的C++代码在不同的系统上产生不同的结果。相同的C++'if'语句,Linux/Windows上的不同结果

#include <cstdio> 
int main() 
{ 
    int a=20, b=14; 
    if(a*1.0/b*(a+1)/(b+1)==2) printf("YES!"); 
    else printf("NO!"); 
} 

编译在Ubuntu Linux 12.04使用GCC 4.6.3它输出YES!

编译在Windows 7上使用GCC 4.6.2它输出NO!

但是,使用:

double c = a*1.0/b*(a+1)/(b+1); 
if (c==2) printf("YES!"); 
... 

将返回YES!两台机器上的

为什么这种差异出现的任何想法?这是由编译器版本不匹配造成的(pathlevel版本号应该不重要)?为什么它实际上输出不!在Windows机器上,而这种情况显然是正确的?

+8

浮点数! – Skizz

+2

大家应该知道的关于浮点算术的东西:http://docs.sun.com/source/806-3568/ncg_goldberg.html – chris

+0

与floatin点数的精确比较是坏主意 – Tibor

回答

12

这只是一个猜测,您需要查看编译器的汇编输出以确认。

有可能一个编译器留下中间结果在一个浮点寄存器中,而另一个编译器将结果写到内存中,将其从80位舍入到64位。也有可能是一个使用SSE,另一个不是。

+1

+1(几乎)每个人都知道FP问题,但你试图猜测**原因**的差异! –

+0

是的,确切地说,谢谢你提出这个问题的原因:-) – rafalcieslak

+2

为了澄清,20/14可以完全使用80位精度表示,但不是32位精度(未尝试64)。 Windows构建将中间值存储在RAM中或使用SSE,而Ubuntu构建将FPU中的中间值保留。 – Skizz

14

因为你正在做的浮点类型,其通常不应当在特定比特精确行为依赖从机器到机器的相等比较(或因编译器,等等)。

可能的原因包括编译器选择何时将浮点结果从宽(80位)浮点寄存器中移出(语言标准和IEEE-754浮点标准都没有提出任何特定要求,AFAIK )。

+6

我认为知道什么属性会很有趣的编译器或处理器负责区别。如果不确切,IEEE浮点应该是一致的。 –

+0

@MarkRansom:由于数字不准确,所以不能保证一致性。仅仅因为所涉及的值的准确性,重新排列操作顺序(在数学上应该一致)可以产生不同的结果。编译器只保证数学一致性,而不是精度一致性 –

+0

@LokiAstari,当结果无法保证匹配时,gcc有一个编译器开关,用于重新排列数学运算。 –

2

这是因为浮点运算的,请尝试使用小量comparisions代替:

#define EPSILON_EQUAL(a,b) (fabs((a)-(b)) < (0.0001f)) 

float f = a*1.0/b*(a+1)/(b+1); 
if(EPSILON_EQUAL(f,2.0f)) printf("YES!"); 
+0

感谢您提供epsilon比较,即使您的答案不能解释为什么会发生此问题 – rafalcieslak

+0

我想这与第一个示例中使用float(在if语句中)的事实有关,在第二个示例中使用双。这里是看起来类似于你的问题:http://stackoverflow.com/questions/7702177/error-due-to-limited-precision-of-float-and-double – marcinj

1

,因为它是不正确的一样,浮点数由于精度问题比较。

在数学三分之二=(0.6666666 .....到无穷大)//小学数学:)不问任何问题。

在计算该计算是浮点单元(类似于CPU,但专用于浮点计算)上进行的。现在这个浮点单元(FPU)可能会给你一个非常接近你的实际答案的数字,但它们并不完全相同。因为它会截断结果。有一个专门用于浮点运算的整个领域。总之,从不在比较中使用浮点数,因为您可能会得到相互冲突的结果。

+0

这是真的,但不能解释为什么它不同于平台。 –

0

测试浮点数之间的平等是有问题的。这是因为四舍五入的错误,并且在互联网上有很多这样的文字。

您可以在谷歌搜索floating point equality看到这个hereherehereherehere,基本上任何结果。

+0

这是事实,但并不能解释为什么它从平台到平台各不相同。 –

+0

@OliCharlesworth,就像我说的那样,这里有很多文字。在我看来,再次解释它毫无意义。 – Shahbaz

相关问题