问题描述
以下程序:
#include <stdio.h>
int main()
{
double val = 1.0;
int i;
for (i = 0; i < 10; i++)
{
val -= 0.2;
printf("%g %s\n", val, (val == 0.0 ? "zero" : "non-zero"));
}
return 0;
}
产生这样的输出:
Produces this output:
0.8 non-zero
0.6 non-zero
0.4 non-zero
0.2 non-zero
5.55112e-17 non-zero
-0.2 non-zero
-0.4 non-zero
-0.6 non-zero
-0.8 non-zero
-1 non-zero
谁能告诉我减去0.2 0.2时,是什么原因造成的错误?这是一个舍入误差或其他什么东西?最重要的是,如何避免这个问题?
Can anyone tell me what is causing the error when subtracting 0.2 from 0.2? Is this a rounding error or something else? Most importantly, how do I avoid this error?
编辑:它看起来像得出的结论是不担心,因为5.55112e-17是非常接近于零(感谢@therefromhere该信息)
It looks like the conclusion is to not worry about it, given 5.55112e-17 is extremely close to zero (thanks to @therefromhere for that information).
推荐答案
其因浮点数字不能被存储在精确的值存储。所以,这是从来没有使用安全 ==
中的浮点值。采用双会增加precision,但同样不会是准确的。比较浮点值,正确的方法是做这样的事情:
Its because floating points numbers can not be stored in memory in exact value. So it is never safe to use ==
in floating point values. Using double will increase the precision, but again that will not be exact. The correct way to compare a floating point value is to do something like this:
val == target; // not safe
// instead do this
// where EPS is some suitable low value like 1e-7
fabs(val - target) < EPS;
编辑:如在评论中指出,这个问题的主要原因是0.2不能准确地存储。所以,当你从一些值减去它,每次造成了一些错误。如果你做这种浮点运算的反复然后在某个点的误差将是明显的。我想说的是,所有浮动点值不能存储,因为有他们的infinites。轻微错误的值通常不是明显,但使用的是连续计算会导致更高的累积误差。
As pointed in the comments, the main reason of the problem is that 0.2 can't be stored exactly. So when you are subtracting it from some value, every time causing some error. If you do this kind of floating point calculation repeatedly then at certain point the error will be noticeable. What I am trying to say is that all floating points values can't be stored, as there are infinites of them. A slight wrong value is not generally noticeable but using that is successive computation will lead to higher cumulative error.
这篇关于经过0.0时的错误减去浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!