双减法精度问题

问题描述 投票:22回答:5

我的同事做了这个实验。

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

java double
5个回答
24
投票

double 在内部存储为一个分数 二进制 -- 譬如 1/4 + 1/8 + 1/16 + ...

价值 0.005 -- 或数值 1.435 --不能作为二进制中的精确分数来存储,所以 double 无法存储确切的数值 0.005,而且减去的值也不太精确。

如果你关心精确的十进制运算,使用 BigDecimal.

你也可以找到 本文 有用的阅读。


3
投票

double和float是 不完全是实数.

在任何范围内有无限数量的实数,但表示它们的位数是有限的! 由于这个原因,双数和浮点数会出现四舍五入的错误。

你得到的数字是最接近的数字,可以用浮点表示的双数来表示。

要了解更多细节,你可能想阅读 本文 [警告:可能是高级别的]。

你可能想使用 BigDecimal 以获得精确的小数[但当你试图获得 1/3].


1
投票

doublefloat 算术永远不会完全正确,因为 "引擎盖下 "发生的四舍五入。

本质上,双数和浮点数可以有无限量的小数,但在内存中,它们必须用一些真实的位数来表示。因此,当你进行这种小数运算时,会发生一个四舍五入的过程,如果你把所有的小数都考虑在内,往往会有很小的偏差。

正如前面所建议的,如果你需要完全精确的数值,那么使用 BigDecimal 的存储方式不同。这里是API


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


-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();  
 }
© www.soinside.com 2019 - 2024. All rights reserved.