相同的C ++'if'语句,在Linux / Windows上有不同的结果

时间:2012-05-09 15:39:27

标签: c++ gcc mingw multiplatform

我发现了一个有趣的案例,相同的C ++代码会在不同的系统上产生不同的结果。

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

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

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

但是,使用:

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

将在两台计算机上返回 YES!

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

5 个答案:

答案 0 :(得分:14)

因为您正在对浮点类型进行相等比较,通常不应该依赖于机器之间(或从编译器到编译器等)的特定位精确行为。

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

答案 1 :(得分:12)

这只是猜测,您需要查看编译器的汇编输出才能确定。

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

答案 2 :(得分:2)

这是因为浮点运算,请尝试使用epsilon比较:

#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!");

答案 3 :(得分:1)

因为由于精度问题而比较浮点数是不正确的。

在数学2/3 =(0.6666666 .....到无穷大)//小学数学:)没有问题。

在计算中,此计算在浮点单元上执行(类似于CPU,但专用于浮点计算)。现在这个浮点单元(FPU)可能会给你一个非常接近你的实际答案的数字,但它们并不完全相同。因为它会截断结果。整个字段专用于浮点运算。总之,在比较中永远不要使用浮点数,因为你可能会得到相互矛盾的结果。

答案 4 :(得分:0)

测试浮点数之间的相等性是有问题的。这是因为舍入错误,互联网上有很多很多文本。

您可以看到此hereherehereherehere以及谷歌搜索floating point equality的任何结果