C++11中引入了NAN, NAN是Not-A-Number的简写,表示不是一个数值,那么下面的代码:
#include <cmath>
#include <iostream>
int main(int argc, const char *argv[]) {
if (NAN == NAN) {
std::cout << "NAN == NAN is true" << std::endl;
} else {
std::cout << "NAN == NAN is false" << std::endl;
}
float ans1 = sqrtf(-1.0f);
if (ans1 == NAN) {
std::cout << "ans1 == NAN is true" << std::endl;
} else {
std::cout << "ans1 == NAN is false" << std::endl;
}
if (std::isnan(ans1)) {
std::cout << "isnan(ans) is true" << std::endl;
} else {
std::cout << "isnan(ans) is false" << std::endl;
}
if (std::isnan(NAN)) {
std::cout << "isnan(NAN) is true" << std::endl;
} else {
std::cout << "isnan(NAN) is false" << std::endl;
}
double v = std::strtod("nan", NULL);
if (std::isnan(v)) {
std::cout << "isnan(v) is true: v = " << v << std::endl;
} else {
std::cout << "isnan(v) is false, v = " << v << std::endl;
}
if (std::isnan((1.0/0.0))) {
std::cout << "isnan(1.0/0.0)) is true" << std::endl;
} else {
std::cout << "isnan(1.0/0.0) is false" << std::endl;
}
if (std::isinf((1.0/0.0))) {
std::cout << "isinf(1.0/0.0)) is true" << std::endl;
} else {
std::cout << "isinf(1.0/0.0) is false" << std::endl;
}
if (std::isinf((1.0/-0.0))) {
std::cout << "isinf(1.0/-0.0)) is true" << std::endl;
} else {
std::cout << "isinf(1.0/-0.0) is false" << std::endl;
}
std::cout << "floor(NAN) = " << (std::floor(NAN)) << std::endl;
std::cout << "floor(NAN) + 1 = " << (std::floor(NAN) +1) << std::endl;
return 0;
}
运行输出是什么呢?
NAN == NAN is false
ans1 == NAN is false
isnan(ans) is true
isnan(NAN) is true
isnan(v) is true: v = nan
isnan(1.0/0.0) is false
isinf(1.0/0.0)) is true
isinf(1.0/-0.0)) is true
floor(NAN) = nan
floor(NAN) + 1 = nan
从上面的代码中我们可以总结到:
- NAN和NAN之间不能用"==" 来比较,负数取平方根计算取来的结果是NAN,但是也不能用 “==” 来判断
- 判断是否为NAN须要用std::isnan来判断
- std::strtod(“nan”, NULL)返回NAN, 其它非"nan"的字符串返回0,比如std::strtod(“otherstring”, NULL)返回0
- 1.0/0.0不是NAN,是无穷大值,C++中用std::isinf来判断是无穷大值或者无穷小值
- NAN可以进行std::floor等数值运算,其结果为NAN, NAN 值进行加减等数值运算也是NAN
对于第五点,NAN又分为quiet_NaN和signal_NaN,前者在进行运算时不会抛出异常,后者会:
参考这里的示例代码:
#include <iostream>
#include <limits>
#include <cfenv>
#pragma STDC_FENV_ACCESS on
void show_fe_exceptions()
{
int n = std::fetestexcept(FE_ALL_EXCEPT);
if(n & FE_INVALID) std::cout << "FE_INVALID is raised\n";
else if(n == 0) std::cout << "no exceptions are raised\n";
std::feclearexcept(FE_ALL_EXCEPT);
}
int main()
{
double snan = std::numeric_limits<double>::signaling_NaN();
std::cout << "After sNaN was obtained ";
show_fe_exceptions();
double qnan = snan * 2.0;
std::cout << "After sNaN was multiplied by 2 ";
show_fe_exceptions();
double qnan2 = qnan * 2.0;
std::cout << "After the quieted NaN was multiplied by 2 ";
show_fe_exceptions();
std::cout << "The result is " << qnan2 << '\n';
}
输出为:
After sNaN was obtained no exceptions are raised
After sNaN was multiplied by 2 FE_INVALID is raised
After the quieted NaN was multiplied by 2 no exceptions are raised
The result is nan