避免算法中的浮点精度误差

时间:2014-03-04 09:25:26

标签: java floating-point floating-point-precision

在我的2D物理模拟(Java)中,我按如下方式计算凸多边形的中心,其中参数 area 是之前计算的多边形的封闭区域。

private Vector2d calculateCenterOfMass(double area) {
    Vector2d center = new Vector2d(0, 0);

    for (int i = 0; i < vertices.length; i++) {
        int j = (i + 1) % vertices.length;
        double factor = (vertices[i].x * vertices[j].y
                       - vertices[j].x * vertices[i].y);
        center.x += (vertices[i].x + vertices[j].x) * factor;
        center.y += (vertices[i].y + vertices[j].y) * factor;
    }
    center.scale(1 / (area * 6));

    return center;
}

我还有一个带有以下几点的多边形我用这个函数来计算质心:

Vector2d [x=325.20399446366355, y=400.0, length=515.5168649182318]
Vector2d [x=375.20399446366355, y=400.0, length=548.4323453822622]
Vector2d [x=375.20399446366355, y=450.0, length=585.8993407245727]
Vector2d [x=325.20399446366355, y=450.0, length=555.2095442399406]

正如您所看到的那样,只需查看 y 值,中心必须位于 y = 425.0 。由于浮点魔法,y值变为 425.00000000000017 。作为参数给出的区域具有精确值 2500.0

如何避免这种情况并获得预期的425.0?

2 个答案:

答案 0 :(得分:3)

BigDecimal可以提供帮助,但我建议您阅读完整的答案。

浮点错误在某种意义上是“正常的”,您不能将每个浮点数精确存储在变量中。有很多资源如何处理这个问题,这里有一些链接:

  1. 如果您不知道实际问题是什么,请检查this
  2. What Every Computer Scientist Should Know About Floating-Poit Arithmetic
  3. IEEE floating point
  4. 为您提供一个理想的工作方式:Quantity Pattern

答案 1 :(得分:1)

使用Double计算并长期存储。