尽管 Microsoft 博客 claim 否则在我的代码中使用
std::isnan
仍然会生成对 C++ 运行时的调用,而不是内联 ucomiss
。
现在我用 x!=x
检查解决了这个问题(因为在这段代码中性能对我来说很重要),但这让我想知道......如果 x!=x
是检查 NaNess 的方法,那不是一个简单的方法吗?实施std::isnan
?
但据我所知,gcc/clang 使用内在函数(并且 msvc 正在尝试)。如果它可以作为正常功能有效实现,他们为什么还要麻烦呢?
所以我有点困惑,因为 SO 上的一个答案声称这是自我比较可以返回 false 的唯一方法。
C++ 标准委员会(终于?)听取了数字学家关于这一问题的意见。在 C++11 之前,习惯用法
x != x
确实被用来检查 NaN 性。没有其他类别的浮点数值适用于该习惯用法。但它从来没有坐得特别好。首先,一些 NaN 可能会引发异常。它还容易受到错误重构的影响。您还可以假设一些浮点标准,例如常见的 IEEE754。
从 C++11 开始,优先使用
std::isnan
。
std::isnan(x)
和 (x != x)
并不完全等同。
最初的问题是用 C++ 提出的,但答案也适用于 C。
ISO/IEC TS 18661-1(已纳入即将推出的 C23 标准)澄清了
isnan()
的行为,即即使参数是信号 NaN,该函数也不会引发任何异常。
另一方面,当
(x != x)
是信号 NaN 时,x
表达式会抛出“无效操作”异常 (FE_INVALID)。
差异仅在于 NaN 信号,因此当信号 NaN 支持关闭时,GCC 会将
std::isnan(x)
优化为 (x != x)
(-fno-signaling-nans
,这是默认值)。
这个堆栈溢出问题是相关的:`isnan()` 和测试相等一样快吗?