双精度浮点数和NaN的比较结果是什么?

6
我有以下程序:
#include <iostream>
#include <cmath>

int main() {
    double a = 1;
    double b = nan("");

    std::cout << (a > b) << std::endl;
    std::cout << (b > a) << std::endl;

    return 0;
}

输出:

0
0

一般来说,从“nan”-“不是数字”的含义可以清楚地看出,与“nan”进行的任何操作基本上都是无意义的。从我在互联网上找到的IEEE-754中,如果FPU中至少有一个操作数是“nan”,则结果也是“nan”,但我没有找到关于正常值和“nan”之间比较的内容,就像上面的例子一样。
标准对此有什么规定?

1
FPU函数和比较的逻辑结果可能是两回事。你的反汇编显示了什么? - tadman
你的代码可能(或可能不会)缺少一个 == 比较。你检查了 <>,但没有检查 ==。也许你想使用 <>=<=> - jotik
4个回答

8
标准对它有何规定?
C++标准没有规定NaN的操作行为,这是未定义的。因此,就C++而言,任何结果都是可能的且被允许的。
ANSI/IEEE Std 754-1985则规定:
比较:每个NaN都必须与任何东西(包括它本身)进行无序比较...。
“无序”具体含义详见该章节中的表格4。简单来说,如果任一操作数是NaN,则比较应返回false,但“!=”应返回true。

2
你看到的0在这种情况下意味着false,因为这是流默认显示false的方式。如果你想将其显示为truefalse,请使用std::boolalpha
std::cout << std::boolalpha << (a > b) << std::endl;

当比较浮点数值时,如果其中一个值是 nan,则 x<y, x>y, x<=y, x>=yx==y 都将评估为 false,而 x!=y 总是为 true。Andrew Koenig 在Dr Dobbs 网站上有一篇很好的文章介绍了这个问题。
想一想,结果不能为 nan,因为比较运算符需要返回布尔值,而布尔值只能有两种状态。

你能提供任何关于这种行为的定义参考吗?(我是指NaN和任何其他正常值之间的比较操作)? - Alex
@Alex - 我已经提供了一篇文章的链接。 - Sean

1

0在这里表示false(假)。 Nan不等于或可与任何值比较,因此操作的结果为false(0)。


你说的很有道理,但是你能提供一些定义这个的参考资料吗? - Alex

0

除了@user2079303的很好的回答之外,还有两个NaN:quiet NaN和signaling NaN。您可以检查您的平台上的std::numeric_limits<T>::has_signaling_NaN是否可用信号NaN。如果它为真并且值包含std::numeric_limits<T>::signaling_NaN,那么

当信号NaN用作算术表达式的参数时,可能会引发适当的浮点异常,并“静音”NaN,即表达式返回一个安静的NaN。

要真正获得FP异常,您可能需要设置FPU控制字(对于x87单元)或MXCSR寄存器(对于SSE2+单元)。这对于x86 / x64平台是正确的,请检查您的平台文档以获取类似的功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接