This question already has answers here:
What is the rationale for all comparisons returning false for IEEE754 NaN values?

(11个答案)


6年前关闭。




相关的IEEE标准定义了数字常数NaN(不是数字),并规定NaN应该比较不等于其自身。这是为什么?

我熟悉的所有语言都执行此规则。但这通常会导致严重的问题,例如将NaN存储在容器中,将NaN放在要排序的数据中时发生意外行为等。更不用说,绝大多数程序员都期望任何对象都等于自己(在他们了解NaN之前),令他们感到惊讶的是,它们增加了错误和困惑。

IEEE标准经过深思熟虑,因此我确信有充分的理由说明NaN等于其自身进行比较会很不好。我只是不知道那是什么。

编辑:请引用What is the rationale for all comparisons returning false for IEEE754 NaN values?作为权威答案。

最佳答案

接受的答案是100%,没有问题WRONG 。不会半途而废,甚至不会略有错误。当这个问题在搜索中弹出时,我担心这个问题会在很长一段时间内使程序员感到困惑和误导。

NaN旨在传播所有计算,像病毒一样感染它们,因此,如果您在深入复杂的计算中遇到某个NaN时,就不会冒出一个明智的答案。否则,根据身份,NaN / NaN应该等于1,以及所有其他结果,例如(NaN / NaN)== 1,(NaN * 1)== NaN,等等。如果您认为计算在某处出错(四舍五入产生了零分母,产生NaN)等,那么您的计算结果可能会非常不正确(或更糟糕:很不正确),而没有明显的原因指示。

探索数学函数的值时,NaN的计算确实有充分的理由。链接文档中给出的示例之一是找到函数f()的zeros()。在用猜测值探查函数的过程中,您很可能会探查其中一个函数f()不产生明智结果的情况。这使zeros()可以看到NaN并继续其工作。

NaN的替代方法是在遇到非法操作(也称为信号或陷阱)后立即触发异常。除了您可能遇到的巨大性能损失外,当时还不能保证CPU将在硬件中支持它,或者OS /语言将在软件中支持它。每个人都是处理浮点数的独特雪花。 IEEE决定将其作为NaN值在软件中进行显式处理,以便可以在任何OS或编程语言中移植。正确的浮点算法通常在所有浮点实现上都是正确的,无论是node.js还是COBOL(hah)。

从理论上讲,您不必设置特定的#pragma指令,设置疯狂的编译器标志,捕获正确的异常或安装特殊的信号处理程序即可使看似相同的算法真正正常工作。不幸的是,一些语言设计师和编译器作者一直在忙于尽其所能撤消此功能。

请阅读有关IEEE 754浮点历史的一些信息。同样,在一个类似的问题上,委员会成员对此做出了回应:What is the rationale for all comparisons returning false for IEEE754 NaN values?

"An Interview with the Old Man of Floating-Point"

"History of IEEE Floating-Point Format"

What every computer scientist should know about floating point arithmetic

07-24 09:45
查看更多