C++中的舍入误差

Rounding error in C++

本文关键字:舍入误差 C++      更新时间:2023-10-16

可能的重复项:
为什么十进制数不能用二进制准确表示?

语言 c++我正在声明一个数组,并在其中保存数字(双精度类型)。然后我开始比较数组中每个元素之间的差异。例如

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

所以当我执行以下操作时

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

条件变假!!

调试后,我发现 0.05 保存在数组中为0.0499......993情况与 0.10 和 0.15 相似

我怎样才能克服这个问题?

切勿比较浮点数以获得完全相等。

你应该阅读每个计算机科学家都应该知道的关于浮点算术的知识来找出原因。

如果你想做精确的计算,你可能想研究使用有理数。可以在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
}

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

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

注意:如果这与货币或货币数据有关,那么只需使用整数/多头等。 使用浮点数/双精度来表示货币是一件坏事,原因如上所述,并在上面的链接中进一步解释。

您有以下几种选择:

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

(2)弄清楚比较双打平等是一个糟糕的策略。 看,当您将数字存储为双精度时,有些数字无法以固定位数的二进制准确表示。 0.05(以及 0.5 5 50 等)是这些数字之一。