2

这是对 IEEE754 NaN 值的所有比较返回 false 的基本原理是什么的后续问题(我认为这是另一个问题,而不是评论)。它有一个很好的答案,但缺少了一件重要的事情:为什么NaN != NaN

我知道 NaN 与数字相比是无序的,因此NaN < x两者NaN > 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 并且每次检查都有一个额外的操作不会成为程序效率低下的原因。同样,没有任何程序受到如此限制,以至于它不能处理一个额外的变量,尤其是一个临时变量。

对我来说,“我需要这样我才能检测到它”的论点没有意义:它与“我需要这样我可以检测到它”NaN!=NaN的论点完全相同。Infinity!=Infinity不,您没有,只需像其他人一样将其与 1/0 进行比较。

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

我不知道以前是否有人问过这个问题,因为原始问题有很多重复项。

边注:

NaN == NaN现在不会改变

虽然 FPU 现在不会改变,但一些编程语言已经改变,所以这NaN == NaN是真的。

编辑:

让我试着澄清一下为什么到目前为止我还没有接受任何答案。到目前为止,我已经阅读了评论,很抱歉我丢了球:我没有解释为什么我不同意,而是问“为什么”,希望你能给出不同的理由。所以让我试着更好地解释我的观点。

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

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

所以是的,当你说“平等没有意义,因为它不是数字”时,我确实听到了你的声音,但我不同意这种说法,因为如果它是真的,那么按照#1,比较 Infinity 也是没有意义的(这也不是一个数字)。尽管根据#2,比较非数字确实有意义。

事实上,我已经阅读了原始问题的所有答案(以及为什么浮点无穷大,与 NaN 不同,相等?其中有一些相关的答案)。为什么是真的所有论点NaN != NaN都归结为“因为它不是一个数字”(已经解决)或“因为有许多不同的位表示”,这被#5反驳了。

我想不出任何逻辑基础来解释为什么 NaN 应该有不同的平等。我并不是说我已经解释了一切:那么我错过了什么?我的一个论点是错误的还是我没有想到的其他原因?这就是为什么我一直在使用“为什么”这个词。如果您不同意,请反驳我或捍卫您的观点。我猜我的上述逻辑至少会有 1 个反驳点,我期待听到它。

我再次为在原始问题中不包括这些内容而道歉,因为我一直在考虑它们。我也很抱歉,这可能会导致现有答案发生重大变化。

4

1 回答 1

3

有几种生产方式NaN

想象一下:

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

如果这两个NaNs 可以表示为数字,那么它们很可能是不同的值。

如果NaN == NaN成立,则此代码段将具有比较它们相等的意外结果。由于大多数程序根据他们的期望进行比较(所以他们使用==, <=,但不使用!==, !<=),返回false不会使这些程序得出错误的结论。

于 2016-06-13T21:29:51.080 回答