从double减去double后精度损失

时间:2012-06-11 09:39:44

标签: java floating-point floating-point-precision

  

可能重复:
  Retain precision with Doubles in java

好的,所以我有以下代码:

int rotation = e.getWheelRotation();
if(rotation < 0)
    zoom(zoom + rotation * -.05); 
else if(zoom - .05 > 0)
    zoom(zoom - rotation * .05);

System.out.println(zoom);

现在,zoom变量的类型为double,最初设置为1.因此,我希望结果类似于1 - .05 = .95; .95 - .05 = .9; .9 - .05 = .85;虽然我打印结果时看起来并非如此,如下所示:

  • 0.95
  • 0.8999999999999999
  • 0.8499999999999999
  • 0.7999999999999998
  • 0.7499999999999998
  • 0.6999999999999997

希望有人能够清楚地解释。我在互联网上搜索,当我们用二进制文件存储浮点数但我仍然不太明白时,我读到它与某些限制有关。我的问题的解决方案并不重要,但我想了解这种行为。

4 个答案:

答案 0 :(得分:3)

Java使用IEEE-754个浮点数。它们并不完全准确。着名的例子是:

System.out.println(0.1d + 0.2d);

...输出0.30000000000000004

你所看到的只是那种不精确的症状。您可以使用double而不是float来提高精确度。

如果您正在处理财务计算,您可能更喜欢BigDecimalfloatdouble

答案 1 :(得分:2)

floatdouble的精确度有限,因为其小数部分表示为2的一系列幂,例如1/2 + 1/4 + 1/8 ......如果你有一个像1/10的数字,它必须近似。

出于这个原因,每当你处理浮点数时,你必须使用合理的舍入,否则你会看到很小的错误。

e.g。

System.out.printf("%.2f%n", zoom);

为了最大限度地减少轮次错误,您可以计算转数,并将此int值除以20.0。你不会以这种方式看到舍入错误,并且它会更快,而且数量更少。

答案 2 :(得分:0)

floatdouble存在精确问题。我建议你看看BigDecimal班级。这应该解决精确问题。

答案 3 :(得分:0)

由于十进制数字(以及整数数字)可以具有无限数量的可能值,因此无法使用标准格式精确地映射到位。计算机通过限制数字可以采用的范围来解决这个问题。

例如,java中的int可以表示大于Integer.MAX_VALUE或2 ^ 31 - 1的任何内容。

对于十进制数字,逗号后面的数字也有问题,也可能是无限的。这可以通过不允许所有十进制值来解决,但是基于2的幂限制到(智能选择的)可能性的数量。这会自动发生但通常无需担心,您可以将0.899999的结果解释为0.9。如果您确实需要显式精度,则必须使用其他数据类型,这可能有其他限制。