【问题标题】:Rounding error in C++ [duplicate]C ++中的舍入错误[重复]
【发布时间】:2011-08-21 18:24:19
【问题描述】:

可能重复:
Why can't decimal numbers be represented exactly in binary?

语言 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++ math programming-languages rounding rounding-error


【解决方案1】:

您永远不应该比较浮点数的精确相等性。

您应该阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic 找出原因。

【讨论】:

    【解决方案2】:

    如果您想进行精确计算,您可能需要考虑使用有理数。可以在 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
    }
    

    【讨论】:

      【解决方案3】:

      浮点数学是计算机无法提供您通常期望的结果的一个领域。参考this

      你可以做的是考虑类似 delta = 0.00001
      并检查fabs((a[3]-a[2]) - (a[2]-a[1])) &lt; delta

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

      【讨论】:

      • “达到[the] par”与此无关;浮点数不准确是一个数学事实。如果您不想要后果,请改用定点。当然,大多数主流语言都不提供原生定点类型,这缺陷。
      • 应该是abs((a[3]-a[2]) - (a[2]-a[1])) &lt; delta,因为错误可能会发生。
      • 您需要检查差异的绝对值与delta
      • @Tomalak:是的,我明白,我已经相应地更改了措辞。 @Mihai:感谢您指出这一点
      • @Sujoy:你加错了abs
      【解决方案4】:

      您有多种选择:

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

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

      【讨论】:

        猜你喜欢
        • 2013-04-02
        • 1970-01-01
        • 2011-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多