相关的 IEEE 标准定义了一个数字常量 NaN(不是数字),并规定 NaN 应该与自身进行比较。这是为什么?
我熟悉的所有语言都实现了这个规则。但它经常会导致严重的问题,例如,当 NaN 存储在容器中时、当 NaN 位于正在排序的数据中时,等等。更不用说,绝大多数程序员都希望任何对象都等于其自身(在他们了解 NaN 之前),因此让他们感到惊讶会增加错误和混乱。
IEEE 标准是经过深思熟虑的,所以我确信 NaN 与其自身进行比较是不好的,这是有充分理由的。我就是不明白那是什么。
编辑:请参考对于 IEEE754 NaN 值,所有比较都返回 false 的理由是什么?作为权威答案。
接受的答案是 100% 毫无疑问是错误的。不是半途而废,甚至是轻微的错误。我担心当这个问题出现在搜索中时,这个问题会在很长一段时间内让程序员感到困惑和误导。
NaN 被设计为在所有计算中传播,像病毒一样感染它们,因此,如果在深入、复杂的计算中遇到 NaN,您不会冒出看似合理的答案。否则,根据恒等式 NaN/NaN 应该等于 1,以及所有其他结果,如 (NaN/NaN)==1、(NaN*1)==NaN 等。如果您想象您的计算在某个地方出错了(舍入产生了零分母,产生 NaN)等,那么你可能会从你的计算中得到非常不正确(或更糟糕:微妙不正确)的结果,而没有明显的指示来说明原因。
当探究数学函数的值时,在计算中使用 NaN 也是有充分理由的;链接文档中给出的示例之一是查找函数 f() 的 zeros()。完全有可能在用猜测值探测函数的过程中,您将探测函数 f() 不会产生合理结果的函数。这允许 Zeros() 看到 NaN 并继续其工作。
NaN 的替代方法是一旦遇到非法操作(也称为信号或陷阱)就触发异常。除了您可能会遇到的巨大性能损失之外,当时无法保证 CPU 会在硬件中支持它,或者操作系统/语言会在软件中支持它;每个人在处理浮点运算时都有自己独特的雪花。IEEE 决定在软件中将其明确处理为 NaN 值,以便它可以跨任何操作系统或编程语言移植。正确的浮点算法在所有浮点实现中通常都是正确的,无论是 node.js 还是 COBOL(哈哈)。
理论上,您不必设置特定的 #pragma 指令、设置疯狂的编译器标志、捕获正确的异常或安装特殊的信号处理程序来使看似相同的算法实际上正常工作。不幸的是,一些语言设计者和编译器编写者一直忙于尽其所能地取消此功能。
请阅读有关 IEEE 754 浮点历史的一些信息。此外,委员会成员还对类似问题做出了回答:对于 IEEE754 NaN 值,所有比较都返回 false 的理由是什么?
《浮点老人访谈录》
《IEEE 浮点格式的历史》
每个计算机科学家都应该了解的浮点运算知识
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)