C++ 怎么判断Nan与Inf C++ 浮点数特殊值检测【数值】

8次阅读

最可靠方案是直接调用 std::isnan 和 std::isinf,它们跨平台、符合 IEEE 754、不被编译器误优化,且需包含 、传浮点类型、避免隐式转换和 /fp:fast。

C++ 怎么判断Nan与Inf C++ 浮点数特殊值检测【数值】

std::isnanstd::isinf 检测 NaN 与 Inf 最可靠

直接调用标准库函数是唯一跨平台、符合 IEEE 754 语义的方案。手写位判断或比较(比如 x != x)虽在部分场景有效,但触发未定义行为或被编译器优化掉的风险极高,尤其开启 -ffast-math 时会彻底失效。

需注意:std::isnanstd::isinf重载函数,必须传入 Floatdoublelong double 类型,传整数会编译失败。

  • #include 是必需的,c++11 起可用
  • float 值应显式调用 std::isnan(float),避免隐式转 double 后精度丢失导致误判
  • MSVC 在 /fp:fast 下可能禁用这些函数的正确性,务必关闭该选项或改用 /fp:precise

std::isnan(x) 为什么x != x 安全

x != x 确实对 NaN 成立(IEEE 754 规定 NaN 不等于任何值,包括自身),但它不是检测 NaN 的合法手段:C++ 标准不保证浮点比较不被优化,Clang/GCC 在 -O2 下可能直接删掉整个条件分支;且它无法区分 signaling NaN 与 quiet NaN。

  • std::isnan 编译为底层 ucomisd(x86-64)等指令,绕过 FP 比较逻辑,直接查 exponent/mantissa 位模式
  • volatile float x = 0.0f / 0.0f; 这类易被优化掉的 NaN 构造,std::isnan 仍能稳定返回 true
  • 若必须用比较法(如嵌入式无标准库),应配合 volatile 修饰和编译器屏障,但强烈不推荐

std::isinf(x) 要区分正负无穷

std::isinf 只判断是否为 ±Inf,不区分符号。需要单独判断正负时,应组合 std::signbit

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

double x = std::numeric_limits::infinity(); if (std::isinf(x)) {     bool is_positive = !std::signbit(x); // true     bool is_negative = std::signbit(x);   // false }
  • std::signbit 返回 bool,对 +0.0 返回 false,对 -0.0 返回 true,也适用于 Inf
  • 不要用 x > 0 判断正无穷——+Inf 比所有有限数大,但 +Inf > +Inffalse,逻辑易错
  • 某些旧库(如 glibc 2.16 前)中 std::isinffloat 参数可能退化为宏,建议统一用 std::isinf(1.0f) 测试是否可用

读取字符串转浮点时 NaN/Inf 的输入兼容性

std::stodstd::stofstd::istringstream 默认支持 "nan""inf""-inf" 等字符串(大小写不敏感),但行为依赖 C 库 locale:

  • 默认 “C” locale 下,std::stod("nan") 返回 quiet NaN,std::stod("inf") 返回 +Inf
  • 非 “C” locale(如 “zh_CN.UTF-8″)可能拒绝这些字符串,抛出 std::invalid_argument
  • std::istringstream 时,需检查 ss.fail()std::isinf/std::isnan 并用,因为失败可能是格式错,也可能是溢出成 Inf

实际处理用户输入时,先转换再检测,比预判字符串内容更健壮。

text=ZqhQzanResources