2011-05-09 77 views
0

可能重复:
Why can't decimal numbers be represented exactly in binary?舍入误差在C++

语言C++ 我声明数组和我保存号(类型双)在它。然后我开始比较数组中每个两个元素之间的差异。 例如

a[1] = 0.05 
a[2] = 0.1 
a[3] = 0.15 

所以 当i执行以下

if(a[3] - a[2] == a[2] - a[1]) 

条件为假!!

调试后,我发现,0.05保存在阵列中作为 0.0499 ...... 993 和情况类似与0.10和0.15

我怎样才能解决这个问题?

+5

一个有用的阅读:[每个计算机科学家应该知道什么关于浮点运算](http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html) – eldarerathis 2011-05-09 14:51:52

+6

Eleveny- bazillion重复。 – 2011-05-09 14:52:00

+0

参见:http:// floating-point-gui。de/ – hammar 2011-05-09 14:52:29

回答

2

浮点数学是计算机不会像您通常所期望的那样给出结果的一个领域。请参阅this以供参考。

你可以做的是考虑像 delta = 0.00001
并检查是否fabs((a[3]-a[2]) - (a[2]-a[1])) < delta

注意:如果这有什么与货币或货币数据,那么只需要使用/长等。使用浮点整数/双待代表金钱是一件坏事,因为上述原因,并在上面的链接中进一步解释。

+0

“达到”标准“与它无关;浮点不精确是一个数学事实。如果你不想要后果,可以使用定点。当然,大多数主流语言不提供本地定点类型,这是一个缺陷。 – 2011-05-09 14:54:05

+1

它应该可能是abs((a [3] -a [2]) - (a [2] -a [1])) Mihai 2011-05-09 14:54:16

+0

你需要检查**绝对**的价值差异对德尔塔 – Alnitak 2011-05-09 14:54:50

3

如果你想做精确的计算,你可能需要考虑使用有理数。有可能在C++中实现一个有理数的类。 Boost.Rational就是这样的一个例子。

如果你想使用浮点数,你可能要为“接近性”做比较,而不是平等的,就像这样:

const float EPSILON = 0.0001; //< Some acceptable limit for equivalence 
float d1 = a[3] - a[2]; 
float d2 = a[2] - a[1]; 

if (fabs(d1 - d2) < EPSILON) { 
    // Consider d1 and d2 eqivalent 
} 
0

你有几种选择:

(1 )使用一个精确存储这些数字的类型。对于这些数字,最简单的可能是使用int并将它们存储为原始数字的100倍。

(2)找出比较双打平等是一个不好的策略。看到,当你把数字存储为双精度时,有一些数字在固定的位数中不能完全用二进制表示。 0.05(以及0.5 5 50等)就是其中的一个数字。