【问题标题】:Inhowfar do IEEE754 floats satisfy LessThanComparable?IEEE754 浮点数在多大程度上满足 LessThanComparable?
【发布时间】:2017-02-19 09:02:35
【问题描述】:

TL;DR包括NaN的IEEE754浮点值是否满足LessThanComparable?

具体来说,问题“Why does Release/Debug have a different result for std::min?”让我查找LessThanComparable:

类型必须与

要求

类型 T 满足 LessThanComparable if

给定

  • a、b 和 c,T 或 const T 类型的表达式

以下表达式必须有效并指定 效果

使用以下属性建立strict weak ordering 关系 (...)

我在the standard 中仔细检查了它,似乎那里的状态基本相同,我查看了严格弱排序的维基百科定义。

Some think 包含 NaN 的 IEEE 浮点值集确实不满足这个概念:任何与 NaN 的比较总是会产生错误,但是我一直在查看定义,根本不NaN 的存在是否会破坏strict weak ordering:

对于维基百科给出的列表:

  • 对于 S 中的所有 x,x
  • 对于 S 中的所有 x、y,如果 x see below
  • 对于 S 中的所有 x、y、z,如果 x
  • 对于 S 中的所有 x、y、z,如果 x 与 y 不可比(x

似乎 Wikipedia 上定义的严格弱排序公理明确指出了可能的 incomparable 值:NaN 在这里似乎是一个不错的候选者?

另一方面,标准说:(25.5/4)

如果我们将equiv(a, b) 定义为!comp(a, b) && !comp(b, a),那么 要求是 comp 和 equiv 都是传递关系:

(4.1) — comp(a, b) && comp(b, c) 暗示 comp(a, c)

(4.2) — equiv(a, b) && equiv(b, c) 暗示 equiv(a, c)

有了这些定义,equiv(x, NaN) 始终是true(因为!comp(a, NaN)==true 和 !comp(Nan, a)==true:与 Nan 比较产生假,否定则产生真)

但显然(4.2)不满足,例如:

 equiv(3.0, NaN) && equiv(NaN, 7.0) **does not** imply equiv(3.0, 7.0)

那么标准定义的不是严格的弱排序,或者——更可能是——我在这里遗漏了什么?

【问题讨论】:

标签: c++ floating-point language-lawyer ieee-754


【解决方案1】:

严格的弱排序要求存在强排序的等价类。 IEEE754 并非如此。

问题不在于存在多个彼此等价的 NaN 值,而是整个 NaN 类相对于实线是无序的。

违反 (4.2) 会导致您从 Wikipedia 引用的第四个要点中的测试也失败(让 y 成为 NaN)。


对于严格弱排序中允许的不可比较性示例,请考虑符号大小整数。那么:

-4

-0 < +0 和 +0 < -0 都不是真的,所以排序很弱。但是由这些等价值形成的类相对于所有其他值是强排序的。

【讨论】:

  • 表达第一句话的另一种方式是,如果项目 x 和 y 相互之间是无序的,那么比较 y 和 z 必须产生与比较 x 和 z 相同的结果。
【解决方案2】:

包括 NaN 在内的 IEEE754 浮点值不满足 LessThanComparable。

如果您从 Wikipedia 获取第 4 个要点并将 uncomparable 替换为 equiv,则您的条件与标准中的相同。


这是一个很好的答案,它基本上回答了我所有的 C++ 疑问。这个:

https://stackoverflow.com/a/8097097/321013

它甚至引用了 std 中的相同段落,就像我在上面的问题最后所做的那样:

如果我们将 equiv(a, b) 定义为 !comp(a, b) && !comp(b, a),那么 要求是 comp 和 equiv 都是传递关系...... equiv(a, b) && equiv(b, c) 蕴含 equiv(a, c)

对于 a = 0.0、b = NaN、c = 1.0、comp = std::less<double>(),这将失败

它还解决了一个有趣的问题。要求:

我一直认为有点奇怪的是标准 用键 type 表示需求,而不是用 添加到容器中的实际键值。我相信你可以 选择阅读此内容不保证 map<double, int> 有 如果实现支持 NaN,则完全定义行为, 无论您是否实际将 NaN 添加到实例中。

【讨论】:

  • 考虑到这一点,是否可以使用标准或 Boost 函数对象来代替 std::less<float> 或者推荐我们自己推出的解决方案?
【解决方案3】:

您似乎是在说 Wikipedia 的定义允许 NaN,但标准的定义不允许。我不认为你是对的。根据维基百科的定义:

对于 S 中的所有 x,y,z,如果 x 与 y 不可比(x

假设 x 是 3.0,y 是 NaN,z 是 7.0。 x 与 y 不可比。 y 与 z 不可比。 x 并非与 z 不可比。

【讨论】:

    猜你喜欢
    • 2013-01-03
    • 2012-02-28
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    相关资源
    最近更新 更多