NaN == 0.0与英特尔C ++编译器?

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

#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: %fnsub: %f %f %fnadd: %f %fndiv: %f %f %fnmul: %f %fn",
        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 == NaNtrue )。 尝试指定/fp:strict/fp:precise并查看是否有帮助。


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

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

以下是IEEE-754:2008所说的内容:

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

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

C标准说:

(C11,F.9.2表达式转换p1)“[...]

x - x→0 0“如果x是一个NaN或无限的”0“,则表达式x - x和0 0不等价。

(这里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的默认选择是完全公平的,但我不会把整个Unix战争都读回这个决定。

链接地址: http://www.djcxy.com/p/14993.html

上一篇: NaN == 0.0 with the Intel C++ Compiler?

下一篇: Why Exynos Octa 5420 is unusually slow