添加和减去双打会产生奇怪的结果
因此,当我使用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)
。