BigDecimal精度问题

介绍

  1.商业计算使用BigDecimal。
  2.使用参数为String的构造函数。
  3.BigDecimal都是不可变的,每一步的运算时,都会产生一个新的对象。所以在做加减乘除后千万要保存操作后的值。

案例

  代码1:

public class Test001 {
	public static void main(String args[]) {
		BigDecimal a = new BigDecimal(1.5);
		BigDecimal a1 = new BigDecimal(329.530);
		System.out.println(a.multiply(a1).setScale(2, BigDecimal.ROUND_HALF_UP));
	}
}

  输出:

494.29

  代码2:

public class Test001 {
	public static void main(String args[]) {
		BigDecimal a = new BigDecimal("1.5");
	  BigDecimal a1 = new BigDecimal("329.530");
		System.out.println(a.multiply(a1).setScale(2, BigDecimal.ROUND_HALF_UP));
	}
}

  输出:

494.30

计算器输出结果:

489.30

  原因解析:
  JDK的描述:参数为dubbo的构造方法的结果具有一定的不可预知性,认为java在写入new BigDecimal(0.1)中这个0.1不是标准的0.1可能是一个无限趋近于0.1的一个小数,虽然表面上等于他。

源码

    public BigDecimal multiply(BigDecimal multiplicand) {
        int productScale = checkScale((long) scale + multiplicand.scale);
        if (this.intCompact != INFLATED) {
            if ((multiplicand.intCompact != INFLATED)) {
                return multiply(this.intCompact, multiplicand.intCompact, productScale);
            } else {
                return multiply(this.intCompact, multiplicand.intVal, productScale);
            }
        } else {
            if ((multiplicand.intCompact != INFLATED)) {
                return multiply(multiplicand.intCompact, this.intVal, productScale);
            } else {
                return multiply(this.intVal, multiplicand.intVal, productScale);
            }
        }
    }

  在这个地方就是判断是不是字符串的,这个this.intCompact 是获取到参数的整数值,如果获取到时一大串数字,那就是dubbo参数传进来的,这里进行判断,从而获取到不同的值。进入到不同的方法进行运算。其实运算原理大致说下,小数转换为整数计算,最后除以10的n次方即可。

原文地址:https://www.cnblogs.com/donghang/p/9233656.html