为什么NaN值的比较与所有其他值的比较行为不同? 也就是说,与运算符==,<=,>=,<,>的所有比较,其中一个或两个值都是NaN,返回false,与所有其他值的行为相反。

我认为这在某种程度上简化了数值计算,但我找不到一个明确的原因,甚至在Kahan的《IEEE 754状态讲义》中也找不到,他详细讨论了其他设计决策。

在进行简单的数据处理时,这种异常行为会造成麻烦。例如,当在C程序中对记录列表w.r.t.某个实值字段进行排序时,我需要编写额外的代码来处理NaN作为最大元素,否则排序算法可能会变得混乱。

编辑: 到目前为止,所有的答案都认为比较nan是没有意义的。

我同意,但这并不意味着正确答案是错误的, 而是一个非布尔型(NaB),幸运的是它并不存在。

所以在我看来,选择返回真或假进行比较是随意的, 对于一般的数据处理来说,如果它符合通常的规律,那将是有利的 (==的反身性,<,==,>的三分), 以免依赖这些定律的数据结构变得混乱。

所以我要求的是打破这些定律的一些具体好处,而不仅仅是哲学推理。

编辑2: 我想我现在明白为什么让NaN最大是一个坏主意了,它会搞砸上限的计算。

NaN != NaN可能是可取的,以避免检测循环中的收敛,例如

while (x != oldX) {
    oldX = x;
    x = better_approximation(x);
}

但是最好是通过比较小极限下的绝对差来写。 所以恕我直言,这是一个相对较弱的论点,打破自反性在NaN。


当前回答

再打个比方。如果我给你两个盒子,告诉你两个盒子里都没有苹果,你会告诉我两个盒子里装的是同样的东西吗?

NaN不包含某物是什么,只包含它不是什么。因此,这些元素不能肯定地说相等。

其他回答

过于简单的回答是,NaN没有数值,因此其中没有任何东西可以与其他任何东西进行比较。

如果您希望nan像+INF一样工作,您可以考虑测试并使用+INF替换nan。

再打个比方。如果我给你两个盒子,告诉你两个盒子里都没有苹果,你会告诉我两个盒子里装的是同样的东西吗?

NaN不包含某物是什么,只包含它不是什么。因此,这些元素不能肯定地说相等。

从wikipedia关于NaN的文章来看,以下做法可能导致NaN:

All mathematical operations> with a NaN as at least one operand The divisions 0/0, ∞/∞, ∞/-∞, -∞/∞, and -∞/-∞ The multiplications 0×∞ and 0×-∞ The additions ∞ + (-∞), (-∞) + ∞ and equivalent subtractions. Applying a function to arguments outside its domain, including taking the square root of a negative number, taking the logarithm of a negative number, taking the tangent of an odd multiple of 90 degrees (or π/2 radians), or taking the inverse sine or cosine of a number which is less than -1 or greater than +1.

由于无法知道这些操作中的哪一个创建了NaN,因此无法对它们进行有意义的比较。

NaN可以被认为是一个未定义的状态/数。类似于0/0未定义或根号(-3)的概念(在浮点数所在的实数系统中)。

NaN被用作这种未定义状态的一种占位符。从数学上讲,未定义并不等于未定义。你也不能说一个未定义值大于或小于另一个未定义值。因此,所有比较返回false。

这种行为在比较根号(-3)和根号(-2)的情况下也很有利。它们都会返回NaN,但它们并不等效,即使它们返回相同的值。因此,在处理NaN时,具有相等总是返回false是理想的行为。

我猜NaN(不是一个数字)的意思就是:这不是一个数字,因此比较它是没有意义的。

这有点像SQL中带有空操作数的算术:它们的结果都为空。

浮点数的比较比较数值。因此,它们不能用于非数值值。因此,NaN不能在数字意义上进行比较。