C++ while循环

#include <iostream>

int main()
{
    double i = 0;
    while(i < 1)
    {
        std::cout << i << std::endl;
        i += 0.1;
    }
    return 0;
}

运行结果:

0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1

问题:当  i  为1时不符合  while循环中 i  <  1 的不等式,为何还会进入循环中输出  1  呢?

浮点数的精度问题,浮点数在计算机中存储是使用 [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;
}

运行效果:

问题就处在这个double类型,Double  和 Float这两个类型都是有精度的,所以,循环十次之后, 这里的i 并不等于1, 而是约等于1. 

具体等于多少,你可以多打印小数点后几位看看。