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

raf*_*lak 3 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!");
}
Run Code Online (Sandbox Code Playgroud)

使用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!");
...
Run Code Online (Sandbox Code Playgroud)

将返回YES!在两台机器上.

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

Oli*_*rth 14

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

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

  • 我认为知道编译器或处理器的哪个属性导致差异会很有趣.如果不精确,IEEE浮点应该是一致的. (6认同)

Mar*_*som 12

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

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

  • 为了澄清,20/14可以使用80位精度精确表示,但不能使用32位精度(未尝试64).Windows构建将中间值存储在RAM中或使用SSE,而Ubuntu构建在FPU中保留中间值. (2认同)