浮点数的精度问题,浮点数在计算机中存储是使用 [IEEE 754](https://baike.baidu.com/item/IEEE%20754/3869922) 标准进行存储的。在使用浮点数进行比较时会存在一个精度问题。
下面我们使用vs自带的调试功能来看一下while循环里发生了什么事情。当i为0时,执行了 i+=0.1后它的值并不是 0.1 而是下图中所显示的 0.1000000001 。
而在我们最后一次循环时,i的值并不是我们想象的为 1, 而是一个近似为1的值 0.9999999999 。因此在下一次比较时会继续的进入循环体内。
我们可以尝试修改程序,使用printf函数的格式化输出,打印出 i 中存储的原数据。
解决浮点数精度比较的办法也非常简单,在林锐的《高质量 C++/C 编程指南》一书中提到不能将浮点数与整数直接进行比较,(截图如下)
解决的办法就是,设置一个精度范围,在此精度范围内我们认为是相等的。
假设有浮点数 a 与 浮点数 b 比较是否相等( a == b,?),我们换个角度想,两数相等则他们的差必为0 。则原式等于判断 a-b == 0 。我们设置一个误差精度为0.01,则在此精度之内的数都可认为与0相等。如下图所示,在蓝色精度范围内的数,我们认为与0相等。
代码:
#include <iostream>
#include <cmath>
// 函数功能,返回a,b 是否相等
bool Comp_double(double a, double b)
{
// 定义一个误差常数,在误差范围内认为两数相等
const double ESP = 1e-14;
//return fabs(a - b) < (ESP);
return (a - b) >= -ESP && (a - b) <= ESP;
}
int main()
{
double i = 0;
while (!Comp_double(i, 1))
{
std::cout << i << std::endl;
//printf("%.17g \n", i);
i += 0.1;
}
return 0;
}
运行效果: