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

Jan*_*sky 1 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);
}
Run Code Online (Sandbox Code Playgroud)

涉及的所有数字都是双精度数,代表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)
Run Code Online (Sandbox Code Playgroud)

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

为什么?这是双重的一些奇怪的行为,我不知道吗?还是我错过了一些更明显的东西?

Pet*_*rey 5

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

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

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