C++中isNaN的全面理解
一、NaN的本质含义
Nan(Not a Number)是浮点数类型(float double long double)特有的一种特殊数值,用于表示无效或未定义的浮点运算结果,它不是一个具体的"数字",
而是一种标记异常运算的状态。
常见产生NaN的场景包括:
1.无效的数学运算:0.0/0.0(零除以零)、sqrt(-1.0)(负数开平方)
2.无意义的数值转换:将无法解析为浮点数的字符串转换为浮点数(如std::stod("abc"),会抛异常,但底层浮点表示中对应NaN)
3.其他特殊运算:inf -inf(无穷大减无穷大) 0.0*inf(零乘以无穷大)
二、C++中判断NaN的标准方法:std::isnan
1.标准C++中,判断一个浮点数是否为NaN的核心函数是std::isnan,它需要包含头文件
2.函数原型
点击查看代码
#include<cmath>
//判断float类型是否为NaN
bool isnan(float arg);
//判断double类型是否为NaN
bool isnan(double arg);
//判断long double类型是否为NaN
bool isnan(long double arg);
三、关键特性:NaN的"自反性失效"
这是NaN最特殊的属性之一:NaN不等于任何值,包括它自身,即对于任意NaN值x,
x==x的结果恒为false。
这也是为什么不能用普通的相等判断来检测NaN(if (x==NaN)完全无效),必须使用std::isnan的核心原因。
点击查看代码
#include<iostream>
#include<cmath>
#include<limits>
int main() {
double nan_val = std::numeric_limits<double>::quiet_NaN();//获取一个安静型NaN
//错误写法:无法检测NaN
if (nan_val == nan_val) {
std::cout << "这行代码永远不会执行" << std::endl;
}
//正确写法:使用std::isnan
if (std::isnan(nan_val)) {
std::cout << "该值是NaN" << std::endl;
}
return 0;
}
四、NaN的两种主要分类
1.安静型NaN(Quiet NaN,QNaN)
特点:产生后不会触发浮点异常,程序可以继续执行,是最常用的NaN类型
获取方式:通过std::numeric_limits
适用场景:大多数需要标记无效数值的场景(如无效运算效果、未初始化的浮点变量)。
2.信号型NaN(Signaling NaN,SNaN)
特点:产生或被访问时会触发浮点异常(信号),可能导致程序中断或进入异常处理流程。
获取方式:通过std::numeric_limits
适用场景:用于调试阶段检测无效浮点运算,生产环境中较少使用。
点击查看代码
#include<iostream>
#include<cmath>
#include<limits>
int main() {
//1.生成NaN值
double zero = 0.0;
double nan1 = zero / zero;//运算产生NaN
double nan2 = std::numeric_limits<double>::quiet_NaN();//安静型NaN
double nan3 = std::numeric_limits<double>::signaling_NaN();//信号型NaN
//2.使用std::isnan判断
std::cout << "nan1是否为NaN:" << (std::isnan(nan1) ? "是" : "否") << std::endl;
std::cout << "nan2是否为NaN:" << (std::isnan(nan2) ? "是" : "否") << std::endl;
std::cout << "nan3是否为NaN:" << (std::isnan(nan3) ? "是" : "否") << std::endl;
//3.验证NaN的自反性失效
double normal_val = 3.14159;
std::cout << "正常值self==" << (normal_val == normal_val ? "true" : "false") << std::endl;
std::cout << "NaN值self==" << (nan1 == nan1 ? "true" : "false") << std::endl;
//4.无穷大不是NaN
double inf_val = 1.0 / zero;
std::cout << "无穷大是否为NaN:" << (std::isnan(inf_val) ? "是" : "否") << std::endl;
return 0;
}


浙公网安备 33010602011771号