如果任一参数是NaN,会导致C/C++ <,<=和==运算符返回true的原因是什么?

Sea*_*ean 44 c c++ nan ieee-754

我对IEEE-754浮点比较规则的理解是,!=如果其中一个或两个参数都是NaN,则所有比较运算符将返回false,而!=运算符将返回true.我可以通过简单的独立测试轻松重现此行为:

for (int ii = 0; ii < 4; ++ii)
{
    float a = (ii & 1) != 0 ? NAN : 1.0f;
    float b = (ii & 2) != 0 ? NAN : 2.0f;
    #define TEST(OP) printf("%4.1f %2s %4.1f => %s\n", a, #OP, b, a OP b ? "true" : "false");
    TEST(<)
    TEST(>)
    TEST(<=)
    TEST(>=)
    TEST(==)
    TEST(!=)
}
Run Code Online (Sandbox Code Playgroud)

这将打印预期结果:(NaN的格式-1.$与MSVC运行时一样)

 1.0  <  2.0 => true
 1.0  >  2.0 => false
 1.0 <=  2.0 => true
 1.0 >=  2.0 => false
 1.0 ==  2.0 => false
 1.0 !=  2.0 => true
-1.$  <  2.0 => false
-1.$  >  2.0 => false
-1.$ <=  2.0 => false
-1.$ >=  2.0 => false
-1.$ ==  2.0 => false
-1.$ !=  2.0 => true
 1.0  < -1.$ => false
 1.0  > -1.$ => false
 1.0 <= -1.$ => false
 1.0 >= -1.$ => false
 1.0 == -1.$ => false
 1.0 != -1.$ => true
-1.$  < -1.$ => false
-1.$  > -1.$ => false
-1.$ <= -1.$ => false
-1.$ >= -1.$ => false
-1.$ == -1.$ => false
-1.$ != -1.$ => true
Run Code Online (Sandbox Code Playgroud)

但是,当我将这段代码粘贴到应用程序内部循环的深处时,执行所有浮点计算时,我得到了这些无法解释的结果:

 1.0  <  2.0 => true
 1.0  >  2.0 => false
 1.0 <=  2.0 => true
 1.0 >=  2.0 => false
 1.0 ==  2.0 => false
 1.0 !=  2.0 => true
-1.$  <  2.0 => true
-1.$  >  2.0 => false
-1.$ <=  2.0 => true
-1.$ >=  2.0 => false
-1.$ ==  2.0 => true
-1.$ !=  2.0 => false
 1.0  < -1.$ => true
 1.0  > -1.$ => false
 1.0 <= -1.$ => true
 1.0 >= -1.$ => false
 1.0 == -1.$ => true
 1.0 != -1.$ => false
-1.$  < -1.$ => true
-1.$  > -1.$ => false
-1.$ <= -1.$ => true
-1.$ >= -1.$ => false
-1.$ == -1.$ => true
-1.$ != -1.$ => false
Run Code Online (Sandbox Code Playgroud)

出于某种原因,<,<=,和==运营商意外地返回true时,一个或两个参数都为NaN.此外,!=操作员意外地返回错误.

这是使用Visual Studio 2010构建的64位代码,运行在Intel Xeon E5-2650上.使用_mm_getcsr(),我已确认CSR寄存器在两种情况下都保持相同的值.

还有什么可以影响像这样的浮点数学的行为?

Sea*_*ean 54

此行为是由于/fp:fastMSVC编译器选项(其中包括)允许编译器执行比较而不考虑正确的NaN行为以生成更快的代码.使用/fp:precise/fp:strict替代使这些比较在呈现NaN参数时表现得如预期.

  • +1并添加了链接.请记住,您也可以使用`#pragma float_control`为特定代码段设置此行为. (14认同)
  • 奇怪的是,/ fp:fast选项仅在较大的应用程序的上下文中触发此无效的NaN行为。当我在独立的main()函数中对此代码应用`/ fp:fast`时,它的行为正确。 (2认同)
  • 谢谢@BillyONeal,这正是我所需要的.很少的代码需要严格的NaN处理. (2认同)