为什么NaN – NaN == 0.0与英特尔C ++编译器?

众所周知,NaNs在算术中传播,但我找不到任何示范,所以我写了一个小testing:

#include <limits> #include <cstdio> int main(int argc, char* argv[]) { float qNaN = std::numeric_limits<float>::quiet_NaN(); float neg = -qNaN; float sub1 = 6.0f - qNaN; float sub2 = qNaN - 6.0f; float sub3 = qNaN - qNaN; float add1 = 6.0f + qNaN; float add2 = qNaN + qNaN; float div1 = 6.0f / qNaN; float div2 = qNaN / 6.0f; float div3 = qNaN / qNaN; float mul1 = 6.0f * qNaN; float mul2 = qNaN * qNaN; printf( "neg: %f\nsub: %f %f %f\nadd: %f %f\ndiv: %f %f %f\nmul: %f %f\n", neg, sub1,sub2,sub3, add1,add2, div1,div2,div3, mul1,mul2 ); return 0; } 

这个例子( 在这里运行 )基本上产生了我所期望的(负面有点奇怪,但有点合理):

 neg: -nan sub: nan nan nan add: nan nan div: nan nan nan mul: nan nan 

MSVC 2015产生类似的东西。 但是,英特尔C ++ 15产生:

 neg: -nan(ind) sub: nan nan 0.000000 add: nan nan div: nan nan nan mul: nan nan 

具体来说, qNaN - qNaN == 0.0

这…不对,对不对? 相关标准(ISO C,ISO C ++,IEEE 754)对此有何评论,为什么编译器之间的行为有所不同?

英特尔C ++编译器中默认的浮点处理是/fp:fast ,它处理NaN的不安全(例如NaN == NaN也是true )。 尝试指定/fp:strict/fp:precise ,看看是否有帮助。

这个 。 不可能是对的,对吧? 我的问题:相关标准(ISO C,ISO C ++,IEEE 754)对此有何评论?

Petr Abdulin已经回答了为什么编译器给出了0.0答案。

这是IEEE-754:2008所说的:

(6.2使用NaN进行操作)“[…]对于具有安静的NaNinput的操作,除了最大和最小操作以外,如果要传送浮点结果,则结果应该是安静的NaN,其应该是inputNaNs“。

所以减去两个安静的NaN操作数的唯一有效结果是一个安静的NaN; 任何其他结果无效。

C标准说:

(C11,F.9.2expression式转换p1)“[…]

x – x→0 0“如果x是一个NaN或无限的”

(这里NaN表示按照F.2.1p1的安静的NaN“本规范没有定义信令NaN的行为,它通常使用术语NaN来表示安静的NaN”)

由于我看到一个反驳英特尔编译器遵守标准的答案,而其他人都没有提到这一点,所以我会指出,GCC和Clang都有一个模式,在这个模式下他们做了一些非常相似的事情。 他们的默认行为是符合IEEE标准的 –

 $ g++ -O2 test.cc && ./a.out neg: -nan sub: nan nan nan add: nan nan div: nan nan nan mul: nan nan $ clang++ -O2 test.cc && ./a.out neg: -nan sub: -nan nan nan add: nan nan div: nan nan nan mul: nan nan 

– 但是如果你以牺牲正确性为代价来求速度,你会得到你所要求的 –

 $ g++ -O2 -ffast-math test.cc && ./a.out neg: -nan sub: nan nan 0.000000 add: nan nan div: nan nan 1.000000 mul: nan nan $ clang++ -O2 -ffast-math test.cc && ./a.out neg: -nan sub: -nan nan 0.000000 add: nan nan div: nan nan nan mul: nan nan 

我认为批评ICC的违约select是完全公平的,但是我不会把整个Unix的战争都看成这个决定。