为什么Java给我带来双倍基本算术的异常结果?

时间:2016-10-18 16:00:59

标签: java double

我正在为在火星上开车的虚拟漫游车提供一些情报,以获取资源。我有以下代码:

public Point getPointFromRoverOffset(double offsetX, double offsetY) {
    double x = offsetX + currentLocation.x;
    double y = offsetY + currentLocation.y;

    if(x > getWorldWidth()) {
        x = x - getWorldWidth();
    }
    else if (x < 0) {
        x = getWorldWidth() + x;
    }

    if(y > getWorldHeight()) {
        y = y - getWorldHeight();
    }
    else if(y < 0) {
        y = getWorldHeight() + y;
    }

    getLog().info("Based on location " + currentLocation.toString());
    getLog().info("Decided that offset (" + offsetX + "," + offsetY + ") = (" + x + "," + y + ")");
    return new Point(x, y);
}

所涉及的所有数字都是双精度数,代表2d平面中的2d向量。

getWorldWidth()和getWorldHeight()都返回20.0

我得到以下奇怪的结果:

[INFO] 16:41 Versatile - Based on location (0.0,6.0)
[INFO] 16:41 Versatile - Decided that offset (0.0,-5.999999999999999) = (0.0,8.881784197001252E-16)

看似输入Y值-5.9(重复出现,双舍入故障),当前Y位置为0.6,因此该值应为0.1。然而它出现了8.88(等)。

为什么呢?这是我不知道的双打的一些奇怪行为吗?或者我错过了一些更明显的东西?

1 个答案:

答案 0 :(得分:5)

8.881784197001252E-16是一个非常小的数字。它大约是0.000000000000000888或8.88 * 10 ^ -16。它是具有轻微舍入误差的值与期望值之间的差异。

如果您需要准确的值,我建议

  • 围绕双打
  • 在计算中使用一个小的允许错误,例如ERR = 1e-6
  • 使用整数(例如,将所有内容缩放1000)
  • 使用BigDecimal。