【问题标题】:NaN comparison rule in C/C++C/C++ 中的 NaN 比较规则
【发布时间】:2023-04-08 16:18:02
【问题描述】:

对一段代码做一些优化,代码的正确性取决于编译器如何处理 NaN。

我阅读了关于 NaN 的 IEEE-754 规则,其中指出:

当有一个或两个操作数时,比较 EQ、GT、GE、LT 和 LE 是 NaN 返回 FALSE。

比较NE,当一个或两个操作数都是NaN时返回TRUE。

上述规则在 C/C++ 中是否强制执行?

【问题讨论】:

    标签: c++ c nan


    【解决方案1】:

    ==!= 运算符似乎受限于 NaNs 的 IEEE 754 行为,正如 @AlexD 的回答中已经指出的那样。

    但是,<math.h> 比较宏需要遵循与 IEEE 754 等效的 NaN 规则。以下来自 C11 草案 N1580 在 7.12.14 Comparison Macros 下指出,<math.h> 比较宏 需要确保,如果 @987654330 中的一个或两个@ 是NaNs 那么:

    • isunordered(x, y)true

    • isgreater(x, y)isgreaterequal(x, y)isless(x, y)islessequal(x, y)都是false

    关系和等式运算符支持数值之间通常的数学关系。对于任何有序数值对,其中一个关系——lessgreaterequal——是正确的。当参数值为NaNs 时,关系运算符可能会引发“无效”浮点异常。 对于一个NaN 和一个数值,或者对于两个NaNs,只有无序关系为真

    C++ 标准只是遵循C 的标准,<math.h> 很重要:

    分类/比较函数的行为与具有相应名称的 C 宏相同 在 7.12.3,分类宏和 7.12.14,C 标准中的比较宏中定义。

    【讨论】:

      【解决方案2】:

      C/C++ 不需要特定的浮点表示,也不需要与NaN 的任何比较都是false

      在 C++ 中,您可以使用 std::numeric_limits::is_iec559 检查所有浮点类型是否满足 IEEE 754:

      static constexpr bool is_iec559;

      56 当且仅当类型符合 IEC 559 标准时为真。217

      57 对所有浮点类型都有意义。


      217) 国际电工委员会标准 559 与 IEEE 754 相同。

      对于其他浮点表示与NaN 的比较 行为方式可能相同,也可能不同。

      事实上,即使代表NaN 本身也不是必需的。见std::numeric_limits<T>::has_quiet_NaN, std::numeric_limits<T>::has_signaling_NaN.

      【讨论】:

      • 这有点误导。该问题一般不询问 IEC 559,而是询问该标准的一个特定方面,即使在无视 IEC 559 的实施中,C 和 C++ 标准也可能直接保证,也可能不保证。
      • 该标准说“具有相同对象表示的两个值(NaN 除外)比较相等”。
      • @a3f 是的,但这本身就没有说明两个具有相同对象表示的 NaN 是否也比较相等。
      • @hvd 我认为关键在于,如果它无视 IEC559,则该标准没有指定任何要求——它们可能比较相等,也可能不相等。如果它支持 IEC559,您只能依赖结果。
      • 我认为当实现不遵循 IEC 559 时,对 NaN 有一个要求,至少在 C:6.5.9 相等运算符(==!=)中:“对于任何一对操作数,恰好其中一个关系为真。”这不允许实现将 NaN 与 SQL NULL 类似地处理,后者与自身比较既不相等也不不相等。
      猜你喜欢
      • 2012-11-15
      • 2013-02-22
      • 2011-07-11
      • 2013-05-24
      • 2016-10-19
      • 1970-01-01
      • 2011-05-29
      • 2017-10-26
      • 1970-01-01
      相关资源
      最近更新 更多