【问题标题】:Are floating point comparisons continuous? If !(a <= b) is (b > a) guaranteed?浮点比较是否连续?如果 !(a <= b) 是 (b > a) 保证?
【发布时间】:2015-03-04 08:09:50
【问题描述】:

是否保证浮点数:

  • (a &lt;= b) 暗示 !(b &gt; a)
  • !(a &lt;= b) 暗示 b &gt; a

我目前正在处理跨语言,但如有必要,您可以在 C、C++ 或 C# 之一中假设 floatdouble。假设不涉及NaN

我假设 IEEE 的规则在这里适用。我不确定他们的订购规则是否暗示上述内容。

我特别担心的是ab 并不总是相同的变量,而是相同的值。它们总是来自完全相同的计算。但是,由于比较是在不同的代码位置完成的,我无法保证它们是否始终是存储/截断形式(最终可能具有扩展精度)。

当我在寻找保证时,答案应该包括做出这些保证的参考资料,或者官方/强烈暗示这些保证。

【问题讨论】:

  • 假设无穷大和 +-0 怎么样?
  • @JamesSnook,没有。这些值可以是 +-Infinity 或 +-0。虽然你可以忽略 +/-0,如果它更容易的话。这些值每次都以相同的方式生成,因此它们不会在 +-0 之间波动。
  • 适用 IEEE 754 规则的假设是危险的。某些语言,包括 C、C++ 和 C#,允许编译器任意使用更高的精度进行某些计算。如果两个结果都向下舍入到 64 位,则两个计算的结果可能相等,但如果以 80 位扩展格式进行比较,则不相等。
  • 这里的各种标准都有保证,但是编译器经常违反这些保证。我会向您推荐gcc bug 323,但您似乎已经知道这一点超过 10 年了。
  • @PatriciaShanahan 如果定义了__STDC_IEC_559__,编译器承诺 IEEE-754 浮点运算有效。然而,这并不意味着它没有错误。此外,您刚才所说的并不完全正确;编译器可以以任意精度进行数学运算,但根据 as-if 规则,任何多余的精度都必须四舍五入。有时不这样做,或者只在需要寄存器溢出时才这样做,这是在论文The pitfalls of verifying floating-point computations 中探讨的一个错误。

标签: floating-point ieee-754


【解决方案1】:

根据 IEEE 754 (2008) 标准(§ 5.11):

可能有四种互斥关系:小于等于大于无序。最后一种情况出现在至少一个操作数是 NaN 时。每个 NaN 都应将 unordered 与一切进行比较,包括它自己。比较应忽略零符号(因此 +0 = -0)。相同符号的无限操作数应该比较相等

所以是的,假设两个参数都不是 NaN,那么这两个陈述都是正确的。

至于使用隐式扩展精度格式,问题在于允许这些意味着它不再严格遵循 IEEE 754 标准。请参阅this excellent answer and discussion 了解启用严格合规性。

更新:据我了解,如果您使用的是最近的标准(例如-std=c99),那么只要您要比较的东西是声明的变量(例如@ 987654323@) 而不是常量(例如if (0.1 &lt; b) ...)。

【讨论】:

  • 我猜想在扩展精度的情况下,它们并不能得到保证。使用非常低的精度作为指导。 5.5 &gt; 5.4!(5 &gt; 5)。我想我必须以某种方式强制截断我的数字。
【解决方案2】:

答案是是的,但这只是因为您排除了 NaN,根据我对 IEEE-754 标准的阅读。通常答案是。该标准的相关部分内容如下:

5.11 比较谓词详解

对于每种支持的算术格式,应该可以比较 一个浮点数据以该格式转换为另一个数据(见 5.6.1)。 此外,以不同格式表示的浮点数据 只要操作数的格式相同,就应具有可比性 基数。

可能有四种互斥关系:小于等于大于,且无序。最后一种情况出现在至少一个操作数是 NaN 时。每个 NaN 都应将 unordered 与 一切,包括它自己。比较应忽略的符号 零(所以 +0 = -0)。相同符号的无限操作数应比较 相等

语言定义了比较结果的传递方式,在 两种方式之一:要么作为识别四种方式之一的关系 上面列出的关系,或作为对谓词的真假响应 命名所需的特定比较。

表 5.1、表 5.2 和表 5.3 在功能上展示了 22 个 不同的有用谓词和否定,具有各种临时和 传统的名称和符号。如果任何一个谓词为真,则每个谓词 表示关系为真。关系“?”表示无序 关系。表 5.2 列出了五个无序信号谓词和 他们的否定会导致无效的操作异常,当 关系是无序的。无效操作异常维护 防止在使用 标准谓词 {=, >} 及其否定,没有 考虑安静 NaN 操作数的可能性。程序 明确考虑安静 NaN 操作数的可能性 使用表 5.3 中不发出信号的无序安静谓词 这样一个无效的操作异常。

除了无效操作之外,比较永远不会发出异常信号 例外。

注意谓词成对出现,每一个都是对 其他;应用诸如 NOT 之类的前缀来否定表中的谓词 5.1、表5.2、表5.3颠倒了其关联条目的真假意义,但不改变是否无序关系 导致无效操作异常。

表 5.1 中的无序安静谓词不表示异常 在安静的 NaN 操作数上:

表 5.1 - 必需的无序安静谓词和否定

表 5.2 中的无序信号谓词,旨在供以下人员使用 编写的程序考虑到 NaN 的可能性 操作数,在安静的 NaN 操作数上发出无效操作异常信号:

表 5.2 - 必需的无序信号谓词和否定

表 5.3 中的无序安静谓词,旨在供以下人员使用 考虑到 NaN 操作数的可能性而编写的程序, 不要在安静的 NaN 操作数上发出异常信号:

表 5.3 - 必需的无序安静谓词和否定

谓词的逻辑否定有两种写法,一种 显式使用NOT,另一个反转关系运算符。 因此,在没有考虑 NaN 可能性的情况下编写的程序 操作数,无序信号谓词的逻辑否定(X = Y) 的不同之处在于它 当 X 和 Y 是时,不会发出无效操作异常信号 无序(除非 X 或 Y 是信号 NaN)。相反,(X = Y) 的逻辑否定可以写成 NOT(X = Y) 或 (X ? Y);在这种情况下,两个表达式在功能上是等效的 到 (X ≠ Y)。

因此,对我来说,由于没有 NaN 排除了 UN 关系,因此剩下的就是集合 EQ LT GT。肯定LT EQ意味着否定GT,否定LT EQ确实是GT

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多