可能重复:
为什么十进制数不能用二进制精确表示?
语言 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++ 我正在声明一个数组并在其中保存数字(双精度类型)。然后我开始比较数组中每两个元素之间的差异。例如
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 等)就是这些数字之一。