双减法精度问题

我的同事做了这个实验:

public class DoubleDemo { public static void main(String[] args) { double a = 1.435; double b = 1.43; double c = a - b; System.out.println(c); } } 

对于这个一年级的操作,我期望这个输出:

 0.005 

但出乎意料的是输出是:

 0.0050000000000001155 

为什么在这么简单的操作中双重失败? 如果double不是这项工作的数据类型,我应该使用什么?

double在内部存储为二进制的分数 – 如1/4 + 1/8 + 1/16 + ...

0.005 – 或值1.435 – 不能以二进制forms存储为精确分数,因此double不能存储精确值0.005 ,并且减去的值不是很精确。

如果您关心精确的十进制算术,请使用BigDecimal

您可能还会发现这篇文章很有用。

double和float 并不是真正的数字

在任何范围内都有无限数量的实数,但只有有限数量的位来表示它们! 因此,对于double和float,预计会出现舍入错误。

您获得的数字是可以用浮点表示中的double表示的最接近的数字。

有关更多详细信息,您可能希望阅读本文 [警告:可能是高级别]。

您可能希望使用BigDecimal来获得精确的十进制数[但是当您尝试获得1/3时,您将再次遇到舍入错误]。

doublefloat算法永远不会完全正确,因为“引擎盖下”会发生舍入。

基本上双精度和浮点数可以有无限的小数,但在内存中它们必须用一些实数位来表示。 因此,当您执行此十进制算术时,会发生舍入过程,如果考虑所有小数,则通常会关闭非常小的量。

如前所述,如果您需要完全精确的值,则使用BigDecimal以不同方式存储其值。 这是API

  //just try to make a quick example to make b to have the same precision as a has, by using BigDecimal private double getDesiredPrecision(Double a, Double b){ String[] splitter = a.toString().split("\\."); splitter[0].length(); // Before Decimal Count int numDecimals = splitter[1].length(); //After Decimal Count BigDecimal bBigDecimal = new BigDecimal(b); bBigDecimal = bBigDecimal.setScale(numDecimals,BigDecimal.ROUND_HALF_EVEN); return bBigDecimal.doubleValue(); }