探究double nan

发布时间:2023-05-24

在数学和计算机领域中,NaN是一个缩写,它代表"Not a Number",是一种数值数据类型,用来表示无效的浮点数。在C++中,NaN是由double类型的值std::numeric_limits<double>::quiet_NaN()生成的。它们主要被用来处理浮点运算异常,以及在浮点数中存储其他元数据信息。

一、什么是double nan

double nan是一个特殊的值,是由double类型的值std::numeric_limits<double>::quiet_NaN()生成的。当计算结果不是实数时,就会产生NaN。常见的产生NaN的情况有除0操作、根号运算负数、精度传递高位等。 在double类型中,各类普通值的表示范围有限,而NAN是数值中的一种特殊表示,仅表示数值无效。NAN无法进行算术或比较操作,并且不应出现在任何算法或模型中。

#include <iostream>
#include <cmath>
#include <limits>
int main() {
    std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
    std::cout << sqrt(-1.0) << '\n';
    std::cout << 0.0/0.0 << '\n';
}

运行结果:

nan
nan
nan

二、double nan的类型

double nan有两种类型:quiet nansignaling nanquiet nan可用于一些数学计算,但signaling nan的使用将引起中断异常,所以一般情况下,程序都会使用quiet nanquiet nan还可进一步分为两种类型:单向quiet nan和双向quiet nan。单向quiet nan用于某些加法、减法和乘法中,而双向quiet nan通常用于某些除法。

三、double nan的应用

在C++编程中,NaN通常用于特殊的计算中,例如龙格-库塔方法。 在龙格-库塔方法中,需要计算两个值(一个用更大的步长进行计算,另一个用更小的步长),以便我们可以进行误差估计。

double k1 = h * initial_derivative(t0,y0);
double k2 = h * initial_derivative(t0+h/2, y0+k1/2);
double k3 = h * initial_derivative(t0+h/2, y0+k2/2);
double k4 = h * initial_derivative(t0+h, y0+k3);
double yc = y0 + 1.0/6 * (k1 + 2*k2 + 2*k3 + k4);
double k1_prime = (h/2) * initial_derivative(t0, y0);
double k2_prime = (h/2) * initial_derivative(t0+h/4, y0+k1_prime/2);
double k3_prime = (h/2) * initial_derivative(t0+3*h/4, y0+3*k2_prime/4);
double k4_prime = h * initial_derivative(t0+h, y0+k3_prime);
double yd = y0 + 1.0/6 * (k1_prime + 2*k2_prime + 2*k3_prime + k4_prime);
double error = (yc - yd)/5;

在上述代码中,如果出现NaN,将导致误差估计失败,需要重新计算。

四、double nan的注意事项

使用double nan时,需要注意以下几点:

  1. NaN的比较应该使用isnan()函数,而不是==!=运算符。因为NaN不等于任何浮点数,包括NaN本身。
if (isnan(x)) {
    std::cout << "x is NaN" << '\n';
} else {
    std::cout << "x is not NaN" << '\n';
}
  1. 在存储double nan时,注意其符号位问题。可以将符号位存为0,表示正数;或者存为1,表示负数。注意,当nan被存储为特殊值时,符号位总是0。
double nanVal = std::numeric_limits<double>::quiet_NaN();
nanVal = std::copysign(nanVal, -1.0);
std::cout << std::isnan(nanVal) << '\n';   // 1
std::cout << nanVal << '\n';              // -nan
  1. 请注意,double nan的几何性质有其独特之处,例如double nan等于任何值,包括本身,因此,任何操作都不应参与到这些计算中。

五、总结

double nan是一种特殊的值,用来表示无效的浮点数,在C++编程中应用广泛。NaN的比较应该使用isnan()函数,而不是==!=运算符。