IEEE754 NaN值返回false的所有比较的基本原理是什么?

为什么比较NaN值的行为与所有其他值有所不同? 也就是说,与运算符==,<=,> =,<,>的所有比较,其中一个或两个值都是NaN返回false,这与所有其他值的行为相反。

我想这会以某种方式简化数值计算,但我找不到明确说明的原因,即使在Kahan的关于IEEE 754状态的讲义中也没有详细讨论其他设计决定。

这种异常行为在进行简单的数据处理时会造成麻烦。 例如,当对C程序中的某些实值字段进行排序时,我需要编写额外的代码来处理NaN作为最大元素,否则排序算法可能会变得混乱。

编辑:到目前为止的答案都认为比较NaN是没有意义的。

我同意,但这并不意味着正确的答案是错误的,而应该是一个非布尔(NaB),幸运的是它不存在。

因此,在我看来,选择比较是真是假,而对于一般的数据处理,如果遵守通常的规律(==的反射性,<,==,>的三分法),将是有利的,以免数据结构依靠这些法律变得混乱。

所以我要求打破这些规律的一些具体优势,而不仅仅是哲学推理。

编辑2:我想我现在明白为什么制作NaN最大值是一个坏主意,它会弄乱上限的计算。

NaN!= NaN可能需要避免检测循环中的收敛,例如

while (x != oldX) {
    oldX = x;
    x = better_approximation(x);
}

然而,最好通过比较绝对差异和小限制来编写。 所以恕我直言,这是打破NaN反身性的一个相对较弱的理由。


我是IEEE-754委员会的成员,我会尝试帮助澄清一些事情。

首先,浮点数不是实数,浮点算术也不能满足实数算术的公理。 三分法并不是真正算术的唯一属性,它不适用于花车,甚至也不是最重要的属性。 例如:

  • 加法不关联。
  • 分配法并不成立。
  • 有没有逆的浮点数。
  • 我可以继续。 不可能指定一个固定大小的算术类型,以满足我们所知和所爱的真正算术的所有属性。 754委员会必须决定弯曲或破坏其中一些。 这是由一些非常简单的原则指导的:

  • 当我们可以的时候,我们匹配真正的算术行为。
  • 如果我们做不到,我们会尽力使违规行为尽可能可预测并且容易诊断。
  • 关于你的评论“这并不意味着正确答案是错误的”,这是错误的。 谓词(y < x)询问y是否小于x 。 如果y是NaN,那么它不小于任何浮点值x ,所以答案必然是错误的。

    我提到三分法不适用于浮点值。 但是,有一个类似的属性确实存在。 754-2008标准第5.11条第2款:

    四种相互排斥的关系是可能的:小于,等于,大于和无序。 最后一种情况出现在至少一个操作数是NaN的情况下。 每个NaN都会将无序与包括它自己在内的所有事物进行比较。

    至于编写额外的代码来处理NaN,通常可能(虽然并不总是很容易)以NaN通过适当的方式构建代码的结构,但情况并非总是如此。 如果不是这样,则可能需要一些额外的代码,但这对代数闭包给浮点运算带来便利的代价是很小的代价。


    附录:许多评论者认为,保持平等和三分法的反身性会更有用,理由是采用NaN = NaN似乎并不能保留任何熟悉的公理。 我承认对这个观点有些同情,所以我想我会重新回顾这个答案并提供更多的背景。

    从与卡汉交谈我的理解是,NaN!= NaN源于两个实用考虑因素:

  • 只要有可能, x == y应该等价于x - y == 0 (除了作为真正的算术定理之外,这使硬件实现比较更加节省空间,这在开发标准时非常重要 -但是,请注意,这违反了x = y =无穷大,所以它不是一个很好的理由;它可以合理地弯曲到(x - y == 0) or (x and y are both NaN) ) 。

  • 更重要的是,当NaN在8087算法中形式化时,没有isnan( )谓词; 有必要为程序员提供一种方便而有效的方法来检测NaN值,而这些方法不依赖于提供类似isnan( )编程语言,这可能需要很多年。 我会引用卡汉自己关于这个问题的文章:

  • 如果没有办法摆脱NaNs,它们就像CRAYs上的Indefinites一样无用; 只要遇到一次,计算就会最好停止,而不是无限期地持续到无限期的结论。 这就是为什么NaN上的一些操作必须提供非NaN结果。 哪些操作? ...例外是C谓词“x == x”和“x!= x”,对于每个无限或有限数x,它们分别为1和0,但如果x不是数(NaN),则反过来; 这些提供了在NaN和谓词IsNaN(x)中缺少单词的语言中NaN和数字之间唯一简单的普通区别。

    请注意,这也是排除返回类似“Not-A-Boolean”的逻辑。 也许这种实用主义错位,并且标准应该要求isnan( ) ,但是这将使得NaN几乎不可能在世界等待编程语言采用的情况下高效且方便地使用多年。 我不相信这会是一个合理的折衷。

    直言:NaN == NaN的结果现在不会改变。 最好学会与它共处,而不是在互联网上抱怨。 如果你想争论一个适合于容器的订单关系也应该存在,我建议你主张你最喜欢的编程语言实现IEEE-754(2008)中标准化的totalOrder谓词。 事实上,它还没有谈到卡汉关心的有效性,这激发了目前的事态。


    NaN可以被认为是一个未定义的状态/数字。 类似于0/0的概念未定义或sqrt(-3)(在浮点生存的实数系统中)。

    NaN被用作这种未定义状态的一种占位符。 在数学上讲,undefined不等于undefined。 你也不能说一个未定义的值大于或小于另一个未定义的值。 因此所有比较都会返回错误。

    在比较sqrt(-3)到sqrt(-2)的情况下,这种行为也是有利的。 他们都会返回NaN,但即使它们返回相同的值,它们也不相同。 因此,在处理NaN时,平等始终返回假是期望的行为。


    抛出另一个类比。 如果我递给你两个盒子,并告诉你他们两个都没有包含苹果,你会告诉我盒子里有同样的东西吗?

    NaN不包含关于什么是什么的信息,只是它不是。 因此,这些因素绝对不能说是平等的。

    链接地址: http://www.djcxy.com/p/10023.html

    上一篇: What is the rationale for all comparisons returning false for IEEE754 NaN values?

    下一篇: What's the difference between equal?, eql?, ===, and ==?