警告浮点数

Caveat floating point

我需要找到三个 Double 类型的值 x、y、z,使得 (x + y) + z == 1.0 和 x + (y + z) == 0.0。我试图在 Scala 上解决这个问题。这个问题与 Is floating point math broken? 有关,但我应该如何找到这样的值?有什么算法可以完成这个任务吗?据我所知,如果分母是 2 的幂,则它会无误地转换为浮点数。我尝试了 0.5、1、0、0.25 之类的值仍然没有成功。谁能帮帮我?

使用正确的 x、y 和 z 值,可以准确地获得 1.0 和 0.0,而无需在比较中使用 epsilon。我在 Java 中编写了我的程序,但该原则将适用于其他使用 IEEE 754 64 位二进制浮点数作为 Double 的语言。

public class Test {
  public static void main(String[] args) {
    double x = -Math.pow(2.0, 53);
    double y = 1.0;
    double z = -x;
    System.out.println((x + y) + z == 1.0);
    System.out.println(x + (y + z) == 0.0);
  }
}

[-Math.pow(2.0, 53), Math.pow(2.0, 53)] 是所有整数值都可以精确表示的双精度范围。在该范围之外,所有奇数都必须四舍五入。将两端的幅度增加 1 需要四舍五入,四舍五入甚至回到它自己。

x + y,符号相反,在范围内,可以精确表示。将 z 添加到结果得到 1.0,即加法的实数结果。另一方面,y + z 具有等号,使得奇数的大小太大而无法精确表示,因此它四舍五入为 z,加上 x 结果为 0.0.