Linux,Mac OS X和Windows之间的数学舍入行为不同

asd*_*sdf 7 c c++ math

HI,

我开发了一些混合的C/C++代码,并进行了一些密集的数值计算.在Linux和Mac OS XI中编译时,在模拟结束后得到非常相似的结果.在Windows中,程序也可以编译,但是我得到了非常不同的结果,有时程序似乎不起作用.

我在所有系统中都使用了GNU编译器.有些朋友建议我添加-frounding-math,现在windows版似乎工作更稳定,但Linux和Os X,他们的结果,根本没有变化.

您能否推荐其他选项以在Win和Linux/OSX版本之间获得更多一致性?

谢谢

PD我也试过-O0(没有优化)并指定-m32

Don*_*eld 10

我无法谈论Windows中的实现,但英特尔芯片包含80位浮点寄存器,并且可以提供比IEEE-754浮点标准中指定的更高的精度.您可以尝试在应用程序的main()中调用此例程(在Intel芯片平台上):

inline void fpu_round_to_IEEE_double()
{
   unsigned short cw = 0;
   _FPU_GETCW(cw);        // Get the FPU control word
   cw &= ~_FPU_EXTENDED;  // mask out '80-bit' register precision
   cw |= _FPU_DOUBLE;     // Mask in '64-bit' register precision
   _FPU_SETCW(cw);        // Set the FPU control word
}
Run Code Online (Sandbox Code Playgroud)

认为这与@Alok讨论的舍入模式不同.

  • 提及80位寄存器的+1.我不知道`_FPU_*`. (2认同)

Alo*_*hal 9

浮点数有四种不同类型的舍入:向零舍入,向上舍入,向下舍入,舍入到最接近的数字.根据编译器/操作系统,默认值可能在不同系统上有所不同.有关以编程方式更改舍入方法,请参阅fesetround.它由C99标准规定,但可能对您有用.

您也可以尝试-ffloat-storegcc选项.这将试图阻止gcc在寄存器中使用80位浮点值.

此外,如果您的结果根据舍入方法而变化,并且差异很大,则表示您的计算可能不稳定.请考虑进行区间分析,或使用其他方法来查找问题.有关更多信息,请参阅浮点计算中的无效评估无效评估?(pdf)和验证浮点计算的缺陷(ACM链接,但如果这对你不起作用,你可以从许多地方获得PDF).