C++ 怎么判断NaN C++ isnan函数检测非数值【数值】

10次阅读

最标准的方式是直接调用 std::isnan,但仅限浮点类型(Floatdouble、long double),需包含头文件;传入整数如 std::isnan(0) 会编译失败。

C++ 怎么判断NaN C++ isnan函数检测非数值【数值】

怎么用 std::isnan 判断 NaN?

直接调用 std::isnan 是最标准的方式,但它只接受浮点类型(floatdoublelong double),不接受整数或指针。传入整数会编译失败,比如 std::isnan(0) 报错 —— 因为没有匹配的重载。

使用前必须包含头文件:c++11 起)。

示例:

#include  #include   int main() {     double x = 0.0 / 0.0;  // 产生 NaN     std::cout << std::isnan(x) << "n";  // 输出 1 }

为什么 val != val 也能判断 NaN?

IEEE 754 规定:NaN 不等于任何值,包括它自己。所以 x != x 成立当且仅当 x 是 NaN(前提是 x 是浮点类型,且未开启 -ffast-math 等破坏 IEEE 语义的编译选项)。

立即学习C++免费学习笔记(深入)”;

这个技巧无需函数调用、无头文件依赖,适合极简场景或模板元编程中规避 std::isnan 的 SFINAE 问题。

但要注意:

  • val != val 在启用 -ffast-math(GCC/Clang)时可能被优化掉,结果恒为 false
  • std::complex 或自定义浮点类不适用
  • 可读性差,团队协作中建议加注释说明意图

常见误用:传入整数、未检查类型、忽略域错误

std::isnan 不是类型安全的“万能检测”——它不会自动转换整数。以下写法都错:

  • std::isnan(5) → 编译失败:找不到匹配函数
  • std::isnan(static_cast(x)) → 强转后丢失 NaN 信息,永远返回 false
  • std::isnan(some_ptr) → 类型不匹配,编译报错

另外,某些老平台(如部分嵌入式 libc)可能不实现 std::isnan,此时需回退到 val != val 或宏 isnan()(来自 ,注意命名空间)。

跨平台兼容性与替代方案

windows MSVC 默认支持 std::isnan(C++11+),但早期 MinGW 可能需要定义 _USE_MATH_DEFINES 并包含 android NDK r21+ 没问题,r19 及更早需确认 STL 版本。

若需最大兼容性,可封装一层:

#include  template constexpr bool is_nan(T x) noexcept {     if constexpr (std::is_floating_point_v) {         return std::isnan(x);     } else {         return false;     } }

这样既能阻止整数误用,又避免宏污染和头文件冲突。

真正容易被忽略的是:NaN 有符号位和 payload,std::isnan 只管“是不是 NaN”,不管它是 quiet 还是 signaling,也不反映 payload 内容 —— 如果业务需要区分,得用 std::fpclassify 或位操作解析二进制表示。

text=ZqhQzanResources