Floating point 为什么NaN不等于NaN?

Floating point 为什么NaN不等于NaN?,floating-point,language-agnostic,nan,ieee-754,Floating Point,Language Agnostic,Nan,Ieee 754,相关IEEE标准定义了一个数值常量NaN(不是数字),并规定NaN应与自身进行比较。为什么呢 我熟悉的所有语言都实现了这个规则。但它通常会导致重大问题,例如,当NaN存储在容器中时,NaN位于正在排序的数据中时,会出现意外行为等。更不用说,绝大多数程序员都希望任何对象都与自身相等(在他们了解NaN之前),因此让他们感到意外会增加错误和混乱 IEEE标准是经过深思熟虑的,所以我相信有一个很好的理由可以解释为什么将NaN与自身等同是不好的。我就是搞不懂那是什么 编辑:请参考作为权威答案。那么,log

相关IEEE标准定义了一个数值常量NaN(不是数字),并规定NaN应与自身进行比较。为什么呢

我熟悉的所有语言都实现了这个规则。但它通常会导致重大问题,例如,当NaN存储在容器中时,NaN位于正在排序的数据中时,会出现意外行为等。更不用说,绝大多数程序员都希望任何对象都与自身相等(在他们了解NaN之前),因此让他们感到意外会增加错误和混乱

IEEE标准是经过深思熟虑的,所以我相信有一个很好的理由可以解释为什么将NaN与自身等同是不好的。我就是搞不懂那是什么

编辑:请参考作为权威答案。

那么,
log(-1)
给出了
NaN
,而
acos(2)
也给出了
NaN
。这是否意味着
log(-1)==acos(2)
?显然不是。因此,
NaN
不等于它本身是完全有道理的

大约两年后再回顾一下,这里有一个“NaN-safe”比较函数:

function compare(a,b) {
    return a == b || (isNaN(a) && isNaN(b));
}

一个很好的属性是:如果
x==x
返回false,那么
x
NaN。

(可以使用此属性检查
x
是否为
NaN

我的原始答案(4年前)从现代角度批评了该决定,但不了解作出该决定的背景。因此,它不能回答这个问题

正确答案如下:

NaN
!=
NaN
源于两个务实的考虑:

[…]在8087算法中将NaN形式化时,没有
isnan()
谓词;有必要为程序员提供一种方便、高效的方法来检测NaN值,这种方法不依赖于编程语言提供的类似于
isnan()
,这可能需要很多年的时间

这种方法有一个缺点:它使NaN在许多与数值计算无关的情况下变得不那么有用。例如,很久以后,当人们想使用
NaN
来表示缺少的值并将它们放入基于散列的容器中时,他们无法做到这一点

如果委员会预见到未来的用例,并认为它们足够重要,那么它们可能会变得更加详细
!(xx)
而不是
x=x
作为对
NaN
的测试。然而,他们的关注点更加务实和狭隘:为数值计算提供最佳解决方案,因此他们认为他们的方法没有问题

===

原始答复:

我很抱歉,虽然我很欣赏这个想法进入了投票结果最高的答案,但我不同意。NaN并不表示“未定义”-参见第7页(搜索“未定义”一词)。正如该文件确认的那样,NaN是一个定义明确的概念

此外,IEEE的方法是尽可能遵循常规的数学规则,当它们不能遵循时,则遵循“最不意外”的规则-参见。任何数学对象都等于它自己,因此数学规则意味着NaN==NaN应该是真的。我看不到任何有效和有力的理由偏离这样一个主要的数学原理(更不用说比较三分法等不太重要的规则)

因此,我的结论如下

IEEE委员会成员并没有很清楚地考虑到这一点,因此犯了一个错误。由于很少有人理解IEEE委员会的方法,或者关心标准对NaN的确切表述(也就是说,大多数编译器对NaN的处理违反了IEEE标准),因此没有人提出警告。因此,该错误现在已嵌入标准中。它不太可能被修复,因为这样的修复会破坏很多现有代码


编辑:来自一个信息丰富的讨论。注意:要获得一个无偏见的视图,您必须阅读整个线程,因为Guido的视图与其他一些核心开发人员的不同。然而,Guido个人对这个话题并不感兴趣,主要遵循Tim Peters的建议。如果有人支持蒂姆·彼得斯的论点
NaN!=NaN
,请在备注中添加;他们很有可能改变我的观点。

事实上,数学中有一个概念叫做“统一”值。这些值是精心构造的扩展,用于协调系统中的外围问题。例如,您可以将复平面中无限远处的环视为一个点或一组点,一些以前自命不凡的问题就会消失。关于集合的基数还有其他例子,你可以证明你可以选择无限连续体的结构,只要| P(A)|>A |,并且没有任何东西断裂

免责声明:我只是在模糊地回忆我在数学学习中的一些有趣的注意事项。如果我在表达上述概念方面做得很糟糕,我表示歉意

如果您想相信NaN是一个单独的值,那么您可能会对某些结果感到不满意,例如等式运算符没有按您期望的方式工作。但是,如果您选择相信NaN更像是由一个单独占位符表示的“坏”的连续统一体,那么您对等式运算符的行为非常满意。换句话说,你看不见你在海里钓到的鱼,但是你钓到了另一条看起来一样但同样臭的鱼。

试试这个:

var a = 'asdf';
var b = null;

var intA = parseInt(a);
var intB = parseInt(b);

console.log(intA); //logs NaN
console.log(intB); //logs NaN
console.log(intA==intB);// logs false

如果intA==intB是真的,这可能会导致您得出a==b的结论,而这显然不是真的


另一种看待它的方式是,NaN只是给你一些关于什么不是的信息,而不是什么是的信息。例如,如果我说‘苹果不是大猩猩’和‘桔子不是大猩猩’,你会认为‘苹果’=‘桔子’是公认的答案吗