为什么IEEE-754决定NaN!= NaN尽管不合逻辑?

时间:2016-06-11 17:03:56

标签: floating-point comparison nan ieee-754 iec10967

这是What is the rationale for all comparisons returning false for IEEE754 NaN values?的后续问题(我认为这是另一个问题而不是评论更好)。它有一个非常好的答案,正好缺少一个重要的事情:为什么NaN != NaN

我知道NaN与数字相比是无序的,因此NaN < xNaN > x都是假的。但这并不能解释为什么平等是倒退的。引用我链接到的问题的答案:

  

有必要为程序员提供一种方便有效的方法来检测NaN值,这些值并不依赖于提供类似isNan()

之类的编程语言

好的:

if((0/0) == x) print "I found NaN!";
//using 0/0 is more readable than using 0x7fc00000 or 0x7ff8000000000000

方便,高效,并且不依赖于编程语言提供的构造。即使编程语言没有定义全局NaN,您也可以自己轻松地创建一个本地(或全局)变量。

单个额外操作肯定效率不高,尤其是因为FPU具有硬编码响应(无需计算)。使用0/0也比不合逻辑的x!=x更方便程序员。

程序很少需要检查NaN,并且每次检查只有一个额外的操作不会是程序效率低下的原因。同样地,没有任何程序如此克制,以至于它无法处理单个额外变量,尤其是临时变量。

对我来说,论证&#34;我需要NaN!=NaN以便我可以检测到它#34;没有意义:它和&#34完全相同的论点;我需要Infinity!=Infinity以便我能够检测到它#34;。不,你不要像其他人一样将它与1/0进行比较。

所以我的问题比原来的问题要窄得多:为什么NaN != NaN

我之前无法确定是否曾经问过这个问题,因为原始问题有很多重复。

旁注:

  

NaN == NaN现在不会改变

虽然FPU现在没有改变,但是一些编程语言已经改变,因此NaN == NaN是真的。

修改

让我试着澄清为什么到目前为止我还没有接受任何答案。到目前为止,我已经阅读了这些评论,对不起,我已经放弃了球:而不是解释为什么我不同意我刚刚问过&#34;为什么&#34;希望你给出不同的理由。所以让我试着更好地解释一下我的观点。

Infinity和NaN在很多方面都很相似。

  1. Infinity和NaN都是概念。无限不是一个数字,它是一个永无止境的概念。如果x是无穷大,那么它表示x是无穷无尽的。 NaN不是数字(duh)并且表示无效状态或在数学上无效的东西。对于数学完备性:无穷大是debatably a "number"但是浮点数接近实数(尽管它们更接近有理数),而无穷大确实不是实数。因此,就FPU和实数行而言,无穷大(所有类型)都不是数字(根据域&#34;数字&#34;的定义)。
  2. 平等并不总是数字平等。如果两个操作数都是数字(不是概念),即使要求FPU执行比较,一般相等也只是数字相等。当一个操作数是Infinity或NaN时使用一般相等性,以便查看另一个操作数是否表示相同的概念。例如,x == Infinity不使用数字相等(因为Infinity不是数字)而是检查x是否代表正无穷大的概念。如果x是&#34;而不是数字&#34;的概念,我同样期望从x == NaN完全相同的东西返回true。但事实并非如此(至于为什么这个问题的重点)。
  3. 可以通过除以0来检索两者:0/0返回NaN,1/0返回Infinity。如果您的语言没有Infinity常量,则x == (1/0)是将x与无穷大进行比较的方法。
  4. 多种口味。有无数种类的无限(因为基数)。然而,FPU没有做出任何区分:Infinity是一个通用的,也是唯一可用的。利用这些结构,例如,不可能询问x是否是可数无穷大。 NaN在概念上只有一种类型(&#34;不是数字&#34;)但它有两种处理方式:安静和信令。我对信号通知一无所知,但根据我的理解,如果你试图比较它会抛出的信号NaN的相等性,因此它不具有相等性,它不完全是在主题上。
  5. 位表示。 NaN有许多不同的位表示,但Infinity只有1(和-Infinity为1)。然而,NaN的所有表示在逻辑上都是完全相同的值,因为它们都代表相同的概念,而不是数字&#34;。在0x7FF8000000000000和0x7FF8000000000001之间没有区别:它们的意思完全相同,并且允许完全相同的数学返回任一结果。你不能问x是sqrt(-1)还是x是log(-1),因为这两个都将返回完全相同的东西:NaN。类似于只有一种Infinity,只有一种(安静的)NaN。是的,有多个位表示,但一个不大于其他位:FPU使用特殊逻辑来处理它们完全相同。对于-0来说同样如此,它具有与+0不同的位但是被视为完全相同。因此,这些位是与逻辑相等无关的实现细节。
  6. (非主题但他们也有特殊数学:x-1不会改变无穷大或NaN的值。
  7. 所以是的,当你说过时,我确实听到了你的声音,而且平等没有意义,因为它不是一个数字&#34;但是我不同意这种说法,因为如果它是真的那么按照#1来比较无限(也不是一个数字)也没有意义。虽然根据#2,比较非数字是有意义的。

    我实际上已经阅读了原始问题的每个答案(以及Why are floating point infinities, unlike NaNs, equal?,其中有一些相关的答案)。所有关于NaN != NaN为什么的论证都归结为&#34;因为它不是一个数字&#34; (已经解决)或&#34;因为有许多不同的位表示&#34;被#5反击。

    我无法想出为什么NaN应该有不同的平等。我并不是说我占了一切:所以我错过了什么?我的一个论点是错的还是还有其他一些我没想到的原因?这就是为什么我一直在露营这个词的原因&#34;为什么&#34;。如果你不同意,那么反驳我或捍卫你的观点。我猜测我的上述逻辑至少会有一个反对点,我期待听到它。

    我再次为在原始问题中不包括这些而道歉,因为我一直在考虑它们。我很抱歉这可能会对现有答案产生重大影响。

1 个答案:

答案 0 :(得分:3)

有几种方法可以生成NaN

想象一下:

double expr1 = 0.0 / 0.0;
double expr2 = Math.log(-1.0);
if (expr1 == expr2) {
  // They are the same
}

这两个NaN,如果它们可以表示为数字,则很有可能成为不同的值。

如果NaN == NaN成立,则此代码段会产生意外结果,将它们视为相等。由于大多数程序都根据预期进行比较(因此他们使用==<=,而不是!==!<=),返回false不会不要让这些程序结束错误的事情。