我写一个循环,一个浮动递增,但我也碰到过下面的例子说明一个浮点运算的问题:
for(float value = -2.0; value <= 2.0; value += 0.2)
std::cout << value << std::endl;
下面是输出:
-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
1.46031e-07
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
到底为什么我收到1.46031e-07
,而不是0
? 我知道这事做与浮点错误,但我不能掌握它为什么发生,我应该做些什么来防止这种情况的发生(如果有一种方法)。 谁能解释(或点我一个链接),这将有助于我明白了吗? 任何输入被理解。 谢谢!
这是因为浮点数只有一定的离散精度。
0.2是不是一个真正的0.2,但在内部表示为一个稍微不同的号码。
这就是为什么你看到的差异。
这是在所有的浮点运算常见的,你真的不能避免。
正如其他人所说,这是做的事实,实数是无限和不可数集,而浮点表示使用有限位数字。 浮点数只能近似实数,甚至在很多简单的情况下并不精确,因为它们的定义。 正如你已经看到, 0.2
实际上不是0.2
,而是代替数字非常接近。 当您添加到这些value
,你积累的误差在每一步。
作为替代方案,尝试使用int
为了你们的迭代和分裂结果拿回来在您需要的领域:
for (int value = -20; value <= 20; value += 2) {
std::cout << (value / 10.f) << std::endl;
}
对我来说,这给:
-2
-1.8
-1.6
-1.4
-1.2
-1
-0.8
-0.6
-0.4
-0.2
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
有没有为避免浮点精度损失明确的解决办法。 我会建议其通过下面的纸一看: 什么每台计算机科学家应该知道浮点运算 。
让我们做你的循环,但增加了输出精度。
码:
for(float value = -2.0; value <= 2.0; value += 0.2)
std::cout << std::setprecision(100) << value << std::endl;
输出:
-2
-1.7999999523162841796875
-1.599999904632568359375
-1.3999998569488525390625
-1.19999980926513671875
-0.999999821186065673828125
-0.79999983310699462890625
-0.599999845027923583984375
-0.3999998569488525390625
-0.19999985396862030029296875
1.460313825418779742904007434844970703125e-07
0.20000015199184417724609375
0.400000154972076416015625
0.6000001430511474609375
0.800000131130218505859375
1.00000011920928955078125
1.20000016689300537109375
1.40000021457672119140625
1.60000026226043701171875
1.80000030994415283203125
使用整数和分割下来:
for(int value = -20; value <= 20; value += 2)
std::cout << (value/10.0) << std::endl;
了解浮点表示一些算法的书或使用互联网。 有很多资源在那里。
其时,你想要什么,似乎是某种方式来获得零当它的东西非常非常接近零。 我们都知道,我们称这个过程为“四舍五入”。 :)所以你为什么不使用它,而打印这些数字。 printf
函数提供了这样的东西好格式的功率。 检查表中下面的链接,如果你不知道如何用printf格式。 (您可以使用格式化的舍入和正确显示号码)的printf REF: http://www.cplusplus.com/reference/cstdio/printf/?kw=printf
- 编辑 -
也许你们当中有些人知道,知道,根据数学1.99999999 ....是一样的2.0。 唯一的区别是表示。 但数量是一样的。
您的浮点问题是一个有点类似于此。 (这仅仅是出于你的澄清。你的问题是不一样的1.9999 ....东西。)