我对IEEE-754浮点比较规则的理解是,除!=
之外的所有比较运算符将返回false,如果其中一个或两个参数都是NaN,而!=
运算符将返回true。我可以很容易地重现此问题有一个简单的独立测试:如果任一参数是NaN,会导致C/C++ <,<=和==运算符返回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(!=)
}
这将打印预期结果:(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。
这是使用Visual Studio 2010构建的64位代码,运行在Intel Xeon E5-2650上。使用_mm_getcsr()
,我已确认CSR注册在两种情况下都保持相同的值。
还有什么可以影响像这样的浮点数学行为?
我讨厌只有迪尔伯特的报价,但“这里有镍,孩子。让自己更好的编译器“ –
你确定他们传统的准C89模式被广告为符合IEEE-754标准?无论如何,你有快速数学或一些这样的启用? – Deduplicator
好像你的编译器正在抛出规范的某些部分以提高性能...... – Synxis