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

用 std::isnan 和 std::isinf 检测 NaN 与 Inf 最可靠
直接调用标准库函数是唯一跨平台、符合 IEEE 754 语义的方案。手写位判断或比较(比如 x != x)虽在部分场景有效,但触发未定义行为或被编译器优化掉的风险极高,尤其开启 -ffast-math 时会彻底失效。
需注意:std::isnan 和 std::isinf 是重载函数,必须传入 float、double 或 long 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 > +Inf为false,逻辑易错 - 某些旧库(如 glibc 2.16 前)中
std::isinf对float参数可能退化为宏,建议统一用std::isinf(1.0f)测试是否可用
读取字符串转浮点时 NaN/Inf 的输入兼容性
std::stod、std::stof 和 std::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
实际处理用户输入时,先转换再检测,比预判字符串内容更健壮。










