加减双精度会得到奇怪的结果

2022-09-01 05:24:18

因此,当我在Java中用Doubles加减时,它会给我带来奇怪的结果。以下是一些:

如果我添加,它会给我.没错。0.0 + 5.15.1

如果我加上,它会给我(重复的次数可能不对)。这是错误的。5.1 + 0.15.1999999999999

如果我减去,它会给我(再次,重复的s可能是关闭的)。这是错误的。4.8 - 0.44.399999999999959

起初,我以为这只是用十进制值添加双精度值的问题,但我错了。以下工作正常:

5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8

现在,添加的第一个数字是另存为变量的双精度值,尽管第二个变量从 .例如:JTextField

//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999

答案 1

在 Java 中,值是 IEEE 浮点数。除非它们是2的幂(或2的幂之和,例如1/8 + 1/4 = 3/8),否则即使它们具有高精度,也无法准确表示。某些浮点运算将加剧这些浮点数中存在的舍入误差。在上述情况下,浮点误差已经变得足够大,可以显示在输出中。double

无论数字的来源是什么,无论是从 解析字符串还是指定文本 - 问题都在浮点表示中继承。JTextFielddouble

解决方法:

  • 如果您知道自己只有这么多个小数点,请使用整数算术,然后转换为小数点:

    (double) (51 + 1) / 10
    (double) (48 - 4) / 10
    
  • 使用大十进制

  • 如果必须使用 ,则可以使用 Kahan 求和算法减少浮点错误。double


答案 2

在Java中,替身使用IEEE 754浮点算术(参见这篇维基百科文章),这本质上是不准确的。使用 BigDecimal 获得完美的十进制精度。为了在印刷中四舍五入,仅接受“相当好”的准确性,请使用.printf("%.3f", x)


推荐