如果任一参数是NaN,会导致C / C ++ <,<=和==运算符返回true?
我对IEEE-754浮点比较规则的理解是,除了!=
之外的所有比较运算符将返回false,如果其中一个或两个参数都是NaN,而!=
运算符将返回true。 我可以通过一个简单的独立testing轻松地重现此行为:
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(!=) }
这将打印预期的结果:(NaN在MSVC运行时格式为-1.$
)
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
但是,当我将这段代码粘贴到我的应用程序的内部循环的深处(所有浮点计算执行的地方)时,我都会得到这些莫名其妙的结果:
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
出于某种原因,当两个或两个参数都是NaN时, <
, <=
和==
运算符意外返回true。 此外, !=
运算符意外地返回false。
这是64位代码,使用Visual Studio 2010构build,运行在Intel Xeon E5-2650上。 使用_mm_getcsr()
,我已经确认CSR寄存器在两种情况下都保持相同的值。
还有什么可以影响这样的浮点math的行为呢?
这是由于/fp:fast
MSVC编译器选项所导致的,该选项允许编译器执行比较,而不考虑正确的NaN行为,以便生成更快的代码。 使用/fp:precise
或/fp:strict
会导致这些比较的行为与NaN参数一致时的预期行为。