Java:添加和减去双打给出了奇怪的结果
所以当我用双打加法或减法时,它给我很奇怪的结果。这里有一些:
So when I add or subtract in Java with Doubles, it giving me strange results. Here are some:
如果我添加 0.0 + 5.1
,它给我 5.1
。这是正确的。
If I add 0.0 + 5.1
, it gives me 5.1
. That's correct.
如果我添加 5.1 + 0.1
,它给我 5.199999999999
(重复 9
的数量可能会关闭)。这是错误的。
If I add 5.1 + 0.1
, it gives me 5.199999999999
(The number of repeating 9
s may be off). That's wrong.
如果我减去 4.8 - 0.4
,它给我 4.39999999999995
(同样,重复的
9
可能会关闭)。这是错误的。
If I subtract 4.8 - 0.4
, it gives me 4.39999999999995
(Again, the repeating 9
s may be off). That's wrong.
起初我以为这只是加上十进制值的双打的问题,但我错了。以下工作正常:
At first I thought this was only the problem with adding doubles with decimal values, but I was wrong. The following worked fine:
5.1 + 0.2 = 5.3
5.1 - 0.3 = 4.8
现在,添加的第一个数字是双重保存为变量,但第二个变量从的JTextField
。例如:
Now, the first number added is a double saved as a variable, though the second variable grabs the text from a JTextField
. For example:
//doubleNum = 5.1 RIGHT HERE
//The textfield has only a "0.1" in it.
doubleNum += Double.parseDouble(textField.getText());
//doubleNum = 5.199999999999999
, double
值为 IEEE浮点数。除非它们是2的幂(或2的幂,例如1/8 + 1/4 = 3/8),否则它们不能被精确地表示,即使它们具有高精度。一些浮点运算将复合这些浮点数中存在的舍入误差。在上述情况下,浮点错误已经变得显着,足以显示在输出中。
In Java, double
values are IEEE floating point numbers. Unless they are a power of 2 (or sums of powers of 2, e.g. 1/8 + 1/4 = 3/8), they cannot be represented exactly, even if they have high precision. Some floating point operations will compound the round-off error present in these floating point numbers. In cases you've described above, the floating-point errors have become significant enough to show up in the output.
数字的来源无关紧要是,是否从一个 JTextField
中解析一个字符串,或者指定一个 double
literal - 问题是在浮点型点表示。
It doesn't matter what the source of the number is, whether it's parsing a string from a JTextField
or specifying a double
literal -- the problem is inherit in floating-point representation.
解决方法:
-
只有这么多小数点,然后使用整数
算术,然后转换为小数位数:
If you know you'll only have so many decimal points, then use integer arithmetic, then convert to a decimal:
(double) (51 + 1) / 10
(double) (48 - 4) / 10
使用 BigDecimal
如果您必须使用 double
,则可以使用卡山求和算法。
If you must use double
, you can cut down on floating-point errors
with the Kahan Summation Algorithm.