双减法精度问题

时间:2012-03-28 15:40:03

标签: java double

我的同事做了这个实验:

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不是这项工作的数据类型,我应该使用什么?

6 个答案:

答案 0 :(得分:19)

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

0.005 - 或值1.435 - 无法以二进制形式存储为精确分数,因此double无法存储精确值0.005,并且减去的值不太准确。

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

您还可以找到this article有用的阅读材料。

答案 1 :(得分:2)

double和float 不完全是实数

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

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

有关详细信息,您可能需要阅读this article [警告:可能是高级别的]。

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

答案 2 :(得分:1)

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

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

如前所述,如果您需要完全准确的值,请使用BigDecimal以不同方式存储其值。 Here's the API

答案 3 :(得分:0)

是的,它使用BigDecimal操作就是这样

private static void subtractUsingBigDecimalOperation(double a, double b) {
  BigDecimal c = BigDecimal.valueOf(a).subtract(BigDecimal.valueOf(b));
  System.out.println(c);
}

enter image description here

答案 4 :(得分:0)

public class BigDecimalExample {

    public static void main(String args[]) throws IOException {

      //floating point calculation
      double amount1 = 2.15;
      double amount2 = 1.10;
      System.out.println("difference between 2.15 and 1.0 using double is: " + (amount1 - amount2));

      //Use BigDecimal for financial calculation
      BigDecimal amount3 = new BigDecimal("2.15");
      BigDecimal amount4 = new BigDecimal("1.10") ;
      System.out.println("difference between 2.15 and 1.0 using BigDecimal is: " + (amount3.subtract(amount4)));       
    }      
}

输出

使用 double 的 2.15 和 1.0 之间的差异是:1.0499999999999998 使用 BigDecmial 的 2.15 和 1.0 之间的区别是:1.05

答案 5 :(得分:-1)

 //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();  
 }