【源码解析】-- BigDecimal源码简要分析以及简单使用

1. 什么是BigDecimal?

在Java中,BigDecimal是一个基础的数据结构,它常常用于需要高精度计算的应用场景,比如表示一个商品的价格、或者是计算商品的购买价格中都经常用到BigDecimal,因为这些数值要求高精度,如果我们使用的是Double、Float等数据类型在一定场景下会导致数值出现一些误差。比如现在有一下代码:

public class BigDecimalAnalyze {

    public static void main(String[] args) {

        double price1=20.15;
        float price2=40.10F;

        BigDecimal bigDecimal1=new BigDecimal(price1);
        BigDecimal bigDecimal2=new BigDecimal(price2);

		//输出实际值
        System.out.println(bigDecimal1);
        System.out.println(bigDecimal2);
    }

}

//控制台输出
20.14999999999999857891452847979962825775146484375
40.09999847412109375

从以上结果中可以分析出,double、float类型表示的数值比原始值稍微偏小一些,虽然现在感觉差的不是特别多,但是万一到时候订单到达比如100W的时候,所差的金额就特别多了,这在实际项目中肯定是不允许的,如果使用BigDecimal计算就能避免以上问题

2. BigDecimal有哪几种构造方法式?

在这里插入图片描述
通过查看源码可以分析出BigDecimal共有以上17中构造方法,但是如果涉及到金额的计算建议使用String入参进行构造

3. BigDecimal的简单使用

在实际项目中使用的比较多的就是BigDecimal的运算,比如常规的加、减、乘、除、取余等。

3.1 BigDecimal加法运算底层实现方法:

 public BigDecimal add(BigDecimal augend) {
        if (this.intCompact != INFLATED) {
            if ((augend.intCompact != INFLATED)) {
                return add(this.intCompact, this.scale, augend.intCompact, augend.scale);
            } else {
                return add(this.intCompact, this.scale, augend.intVal, augend.scale);
            }
        } else {
            if ((augend.intCompact != INFLATED)) {
                return add(augend.intCompact, augend.scale, this.intVal, this.scale);
            } else {
                return add(this.intVal, this.scale, augend.intVal, augend.scale);
            }
        }
    }

 private static BigDecimal add(BigInteger fst, int scale1, BigInteger snd, int scale2) {
 	    //保留多少位小数
        int rscale = scale1;
        long sdiff = (long)rscale - scale2;
        
        //判断是否需要保留小数
        if (sdiff != 0) {
            if (sdiff < 0) {
                int raise = checkScale(fst,-sdiff);
                rscale = scale2;
                fst = bigMultiplyPowerTen(fst,raise);
            } else {
                int raise = checkScale(snd,sdiff);
                snd = bigMultiplyPowerTen(snd,raise);
            }
        }
        
        BigInteger sum = fst.add(snd);
        return (fst.signum == snd.signum) ?
                new BigDecimal(sum, INFLATED, rscale, 0) :
                valueOf(sum, rscale, 0);
    }

从以上源码中,可以简单的发现最终结果还是会返回一个新的BigDecimal对象,当然具体实现不止以上列出来的一个。

//加法运算
 BigDecimal result1 = bigDecimal1.add(bigDecimal2);

 System.out.println("未进行舍入操作的结果:"+result1);

 //四舍五入运算
 result1 = result1.setScale(2, BigDecimal.ROUND_HALF_DOWN);

 System.out.println("结果四舍五入:"+result1);

 //使用String类型作为入参
 BigDecimal price3=new BigDecimal("20.15");
 BigDecimal price4=new BigDecimal("40.10");

 //进行加法运算
 BigDecimal result2=price3.add(price4);

 System.out.println("字符串入参未做任何处理的结果"+result2);

//控制台打印的结果
未进行舍入操作的结果:60.24999847412109232891452847979962825775146484375
结果四色五入:60.25
字符串入参未做任何处理的结果60.25

从以上代码中可以分析出,通过BigDecimal的底层方法可以实现结果舍入操作,这里需要注意的是,通过String入参构造的BigDecimal运算出来的结果不需要多于的舍入操作

3.2 BigDecimal减法操作

 //减法运算
 BigDecimal result3=bigDecimal1.subtract(bigDecimal2);
 System.out.println("未做处理的减法操作:"+result3);

 BigDecimal result4=result3.setScale(2,BigDecimal.ROUND_HALF_DOWN);
 System.out.println("进行了四舍五入的减法操作:"+result4);

 BigDecimal result5=price3.subtract(price4);
 System.out.println("字符串减法运算:"+result5);

//控制台打印结果
未做处理的减法操作:-19.94999847412109517108547152020037174224853515625
进行了四舍五入的减法操作:-19.95
字符串减法运算:-19.95

BigDecimal中乘法操作使用multiply()方法、除法操作使用divide()方法操作、取余使用divideAndRemainder()方法。

发布了132 篇原创文章 · 获赞 55 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_43199016/article/details/104768202