为什么NaN不等于NaN?
这个问题在这里已经有了答案:
接受的答案是100%,毫无疑问是错误的 。 没有中途错误或者甚至有点不对。 我担心这个问题会在查询中弹出这个问题很长一段时间时混淆并误导程序员。
NaN被设计用来在所有计算中传播,像病毒一样感染它们,所以如果你在NaN上进行深入复杂的计算,那么你不会冒出一个看似合理的答案。 否则通过身份NaN / NaN应该等于1,以及所有其他后果,如(NaN / NaN)== 1,(NaN * 1)== NaN等。如果您认为您的计算出错了某处(舍入产生了零分母,产生NaN)等等,那么你的计算结果可能会大得不正确(或者更糟糕:不正确),但是为什么没有明显的指标。
在探测数学函数的值时,NaN在计算中也有很好的理由; 链接文档中给出的例子之一是找到函数f()的零()。 在使用猜测值探测函数的过程中,完全有可能探测函数f()不会产生明显结果的函数。 这允许零()看到NaN并继续它的工作。
NaN的替代方案是在遇到非法操作时立即触发异常(也称为信号或陷阱)。 除了可能遇到的巨大性能损失之外,当时还不能保证CPU可以在硬件中支持它,或者OS /语言将在软件中支持它; 每个人在处理浮点时都是自己独特的雪花。 IEEE决定将其作为NaN值在软件中明确处理,因此它可以跨任何操作系统或编程语言移植。 正确的浮点算法通常在所有浮点实现中都是正确的 ,无论是node.js还是COBOL(hah)。
理论上,您不必设置特定的#pragma指令,设置疯狂的编译器标志,捕获正确的异常,或者安装特殊的信号处理程序,以使看起来相同的算法实际上正常工作。 不幸的是,一些语言设计人员和编译器编写人员正忙于尽其所能地取消这一功能。
请阅读有关IEEE 754浮点历史记录的一些信息。 对于委员会成员回答的类似问题,这个答案也是这样的:所有比较都返回错误的IEEE754 NaN值的基本原理是什么?
“浮点老人专访”
“IEEE浮点格式的历史”
每个计算机科学家应该知道什么是浮点运算
那么, log(-1)
给出NaN
,而acos(2)
也给出NaN
。 这是否意味着log(-1) == acos(2)
? 显然不是。 因此, NaN
不等于自身是完全合理的。
差不多两年后再次访问这里,这是一个“NaN安全”比较函数:
function compare(a,b) {
return a == b || (isNaN(a) && isNaN(b));
}
我的原始答案(从4年前开始)在不了解做出决定的背景的情况下批评了现代视角的决定。 因此,它不回答这个问题。
这里给出了正确的答案:
NaN
!= NaN
源于两个实用考虑因素:
当NaN在8087算法中被正式化时,没有isnan( )
谓词; 有必要为程序员提供一种方便而有效的方法来检测NaN值,而这些方法不依赖于提供类似isnan( )
编程语言,这可能需要很多年
这种方法有一个缺点:它使NaN在许多与数值计算无关的情况下不太有用。 例如,很久以后,当人们想用NaN
来表示缺失值并将它们放入基于散列的容器中时,他们无法做到这一点。
如果委员会预见到未来的使用案例,并认为它们足够重要,那么他们本可以用更详细的!(x<x & x>x)
代替x!=x
作为NaN
的测试。 然而,他们的重点更加务实和狭隘:为数字计算提供最佳解决方案,因此他们认为他们的方法没有问题。
===
原始答案:
我很抱歉,就像我赞赏进入最高票数的答案的想法一样,我不同意它。 NaN并不意味着“未定义” - 请参阅http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF,第7页(搜索单词“undefined”)。 正如该文件所证实的那样,NaN是一个明确定义的概念。
此外,IEEE的做法是尽可能遵循常规的数学规则,当他们不能时,遵循“最小惊喜”规则 - 请参阅https://stackoverflow.com/a/1573715/336527。 任何数学对象都等于它自己,所以数学规则意味着NaN == NaN应该是真的。 我看不出有任何有效而有力的理由偏离这样一个主要的数学原理(更不用说比较的三分法等较不重要的规则了)。
因此,我的结论如下。
IEEE委员会成员没有十分清楚地认为这一点,并犯了一个错误。 由于很少有人理解IEEE委员会的做法,或者关心NaN的标准究竟是怎么说的(即:大多数编译器对NaN的处理违反了IEEE标准),没有人提出警告。 因此,这个错误现在已经嵌入到标准中。 它不太可能被修复,因为这样的修复会破坏很多现有的代码。
编辑:这是一篇来自非常丰富讨论的文章。 注意:为了获得公正的观点,你必须阅读整个主题,因为Guido对其他一些核心开发人员有不同的看法。 然而,Guido对这个主题并不感兴趣,并且大部分遵循了Tim Peters的建议。 如果任何人有Tim Peters的论点赞成NaN != NaN
,请将它们添加到评论中; 他们有很好的机会改变我的观点。