【发布时间】:2023-04-08 16:18:02
【问题描述】:
对一段代码做一些优化,代码的正确性取决于编译器如何处理 NaN。
我阅读了关于 NaN 的 IEEE-754 规则,其中指出:
当有一个或两个操作数时,比较 EQ、GT、GE、LT 和 LE 是 NaN 返回 FALSE。
比较NE,当一个或两个操作数都是NaN时返回TRUE。
上述规则在 C/C++ 中是否强制执行?
【问题讨论】:
对一段代码做一些优化,代码的正确性取决于编译器如何处理 NaN。
我阅读了关于 NaN 的 IEEE-754 规则,其中指出:
当有一个或两个操作数时,比较 EQ、GT、GE、LT 和 LE 是 NaN 返回 FALSE。
比较NE,当一个或两个操作数都是NaN时返回TRUE。
上述规则在 C/C++ 中是否强制执行?
【问题讨论】:
== 和 != 运算符似乎不受限于 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
关系和等式运算符支持数值之间通常的数学关系。对于任何有序数值对,其中一个关系——
less、greater和equal——是正确的。当参数值为NaNs 时,关系运算符可能会引发“无效”浮点异常。 对于一个NaN和一个数值,或者对于两个NaNs,只有无序关系为真。
C++ 标准只是遵循C 的标准,<math.h> 很重要:
分类/比较函数的行为与具有相应名称的 C 宏相同 在 7.12.3,分类宏和 7.12.14,C 标准中的比较宏中定义。
【讨论】:
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.
【讨论】:
== 和 !=)中:“对于任何一对操作数,恰好其中一个关系为真。”这不允许实现将 NaN 与 SQL NULL 类似地处理,后者与自身比较既不相等也不不相等。