添加和减去双打会产生奇怪的结果

因此,当我使用Doubles在Java中添加或减去时,它会给我带来奇怪的结果。 这里有一些:

如果我添加0.0 + 5.1 ,它会给我5.1 。 那是对的。

如果我添加5.1 + 0.1 ,它会给我5.199999999999 (重复9秒的数量可能会关闭)。 那是错的。

如果我减去4.8 - 0.4 ,它会给我4.39999999999995 (同样,重复的9秒可能会关闭)。 那是错的。

起初我以为这只是添加带小数值的双打的问题,但我错了。 以下工作正常:

 5.1 + 0.2 = 5.3 5.1 - 0.3 = 4.8 

现在,添加的第一个数字是保存为变量的double,尽管第二个变量从JTextField获取文本。 例如:

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

在Java中, double值是IEEE浮点数 。 除非它们是2的幂(或2的幂的总和,例如1/8 + 1/4 = 3/8),否则即使它们具有高精度,也不能精确地表示它们。 某些浮点运算会使这些浮点数中出现的舍入误差复杂化。 在上面描述的情况下,浮点错误已经变得非常重要,足以显示在输出中。

无论数字的来源是什么,无论是从JTextField解析字符串还是指定double字面 – 问题是在浮点表示中inheritance。

解决方法:

  • 如果你知道你只有这么多小数点,那么使用整数运算,然后转换为小数:

     (double) (51 + 1) / 10 (double) (48 - 4) / 10 
  • 使用BigDecimal

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

在Java中,双精度使用IEEE 754浮点运算(参见本维基百科文章),这本身就是不准确的。 使用BigDecimal获得完美的小数精度。 要打印圆形,仅接受“相当好”的准确度,请使用printf("%.3f", x)