为什么 NaN 不等于 NaN? [英] Why is NaN not equal to NaN?

查看:38
本文介绍了为什么 NaN 不等于 NaN?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

相关的 IEEE 标准定义了一个数字常量 NaN(不是数字),并规定 NaN 应该与自身不相等.这是为什么呢?

The relevant IEEE standard defines a numeric constant NaN (not a number) and prescribes that NaN should compare as not equal to itself. Why is that?

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

All the languages I'm familiar with implement this rule. But it often causes significant problems, for example unexpected behavior when NaN is stored in a container, when NaN is in the data that is being sorted, etc. Not to mention, the vast majority of programmers expect any object to be equal to itself (before they learn about NaN), so surprising them adds to the bugs and confusion.

IEEE 标准经过深思熟虑,因此我确信 NaN 与自身进行比较是不好的,这是有充分理由的.我就是不知道是什么.

IEEE standards are well thought out, so I am sure there is a good reason why NaN comparing as equal to itself would be bad. I just can't figure out what it is.

请参考 对于 IEEE754 NaN 值返回 false 的所有比较的基本原理是什么? 作为权威答案.

please refer to What is the rationale for all comparisons returning false for IEEE754 NaN values? as the authoritative answer.

推荐答案

我最初的回答(从 4 年前开始)从现代的角度批评了这个决定,而不了解做出决定的背景.因此,它没有回答问题.

My original answer (from 4 years ago) criticizes the decision from the modern-day perspective without understanding the context in which the decision was made. As such, it doesn't answer the question.

这里给出了正确答案:

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

NaN != NaN originated out of two pragmatic considerations:

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

[...] There was no isnan( ) predicate at the time that NaN was formalized in the 8087 arithmetic; it was necessary to provide programmers with a convenient and efficient means of detecting NaN values that didn’t depend on programming languages providing something like isnan( ) which could take many years

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

There was one disadvantage to that approach: it made NaN less useful in many situations unrelated to numerical computation. For example, much later when people wanted to use NaN to represent missing values and put them in hash-based containers, they couldn't do it.

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

If the committee foresaw future use cases, and considered them important enough, they could have gone for the more verbose !(x<x & x>x) instead of x!=x as a test for NaN. However, their focus was more pragmatic and narrow: providing the best solution for a numeric computation, and as such they saw no issue with their approach.

===

原答案:

很抱歉,尽管我很欣赏投票最多的答案中的想法,但我不同意它.NaN 并不意味着未定义" - 请参阅 http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF,第 7 页(搜索未定义"一词).正如该文件所证实的,NaN 是一个定义明确的概念.

I am sorry, much as I appreciate the thought that went into the top-voted answer, I disagree with it. NaN does not mean "undefined" - see http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF, page 7 (search for the word "undefined"). As that document confirms, NaN is a well-defined concept.

此外,IEEE 的方法是尽可能遵循常规数学规则,如果不能,则遵循最小意外"规则 - 请参阅 https://stackoverflow.com/a/1573715/336527.任何数学对象都等于它自己,所以数学规则意味着 NaN == NaN 应该是 True.我看不出有任何有效和有力的理由来偏离这样一个主要的数学原理(更不用说不太重要的比较三分法规则等).

Furthermore, IEEE approach was to follow the regular mathematics rules as much as possible, and when they couldn't, follow the rule of "least surprise" - see https://stackoverflow.com/a/1573715/336527. Any mathematical object is equal to itself, so the rules of mathematics would imply that NaN == NaN should be True. I cannot see any valid and powerful reason to deviate from such a major mathematical principle (not to mention the less important rules of trichotomy of comparison, etc.).

因此,我的结论如下.

IEEE 委员会成员对此没有想得很清楚,犯了一个错误.由于很少有人了解 IEEE 委员会的方法,或者关心标准对 NaN 的确切说法(也就是说:大多数编译器对 NaN 的处理无论如何都违反了 IEEE 标准),所以没有人发出警报.因此,这个错误现在嵌入到标准中.它不太可能被修复,因为这样的修复会破坏很多现有代码.

IEEE committee members did not think this through very clearly, and made a mistake. Since very few people understood the IEEE committee approach, or cared about what exactly the standard says about NaN (to wit: most compilers' treatment of NaN violates the IEEE standard anyway), nobody raised an alarm. Hence, this mistake is now embedded in the standard. It is unlikely to be fixed, since such a fix would break a lot of existing code.

这是一篇文章非常翔实的讨论.注意:要获得公正的观点,您必须阅读整个线程,因为 Guido 与其他一些核心开发人员的观点不同.然而,Guido 个人对这个话题并不感兴趣,并且在很大程度上遵循了 Tim Peters 的建议.如果有人有 Tim Peters 支持 NaN != NaN 的论点,请在评论中添加它们;他们很有机会改变我的看法.

Here is one post from a very informative discussion. Note: to get an unbiased view you have to read the entire thread, as Guido takes a different view to that of some other core developers. However, Guido is not personally interested in this topic, and largely follows Tim Peters recommendation. If anyone has Tim Peters' arguments in favor of NaN != NaN, please add them in comments; they have a good chance to change my opinion.

这篇关于为什么 NaN 不等于 NaN?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆