关于BigDecimal日常使用中的一些注意点

关于BigDecimal日常使用中的一些注意点

最近在公司的价格计算需求中,因为精度的需要,使用到了BigDecimal。但是本人在使用BigDecimal踩到了一些坑,特此记录一下,并且希望能够帮助到后来者。

BigDecimal的初始化赋值

关于BigDecimal的初始化问题,我这里强烈建议大家采用String类型对其进行数据初始化,因为采用基本数据类型初始化再进行运算会出现很奇怪的运算结果:

   //采用String进行初始化赋值
        BigDecimal num = new BigDecimal("0.005");
        BigDecimal price = new BigDecimal("0.002");

        //使用基本数据类型进行赋值
        BigDecimal num2 = new BigDecimal(0.005);
        BigDecimal price2 = new BigDecimal(0.002);

        System.out.println("采用String类型初始化BigDecimal:"+price.multiply(num));
        System.out.println("采用基本数据类型初始化BigDecimal:"+price2.multiply(num2));

运行结果:
下面给大家贴下采用不同类型初始化值进行运算产生的差异:
在这里插入图片描述
造成这样的原因为:不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。而BigDecimal无论是使用int类型,还是double类型,计算结果都是不准确的。
必须使用采用String类型初始化的构造方法!

BigDecimal的基本运算方式

java.math.BigDecimal 不是基本数据类型,而是一个封装类,所以我们平常对基本数据类型的操作例如:直接 +,-,*,\ 是行不通的,而是通过使用类的方法。
加法 :add()函数
减法 :subtract()函数
乘法 :multiply()函数
除法 :divide()函数
绝对值 :abs()函数

关于BigDecimal出现0 E-8等情况

问题的原因出在:BigDecimal的值小数点位数达到8位,Java自动采用科学计数法进行统计。

  //采用String进行初始化赋值
        BigDecimal num = new BigDecimal("0.005");//三位小数点
        BigDecimal price = new BigDecimal("0.0002");
        BigDecimal num2 = new BigDecimal("0.0005");//四位小数点
   		System.out.println("七位小数点的运算:"+price.multiply(num));
   		System.out.println("八位小数点的运算:"+price.multiply(num2));     

输出结果:
在这里插入图片描述

BigDecimal判断:是否为空,是否为0

我需要从实体类从获取price单价,num数量(都为BigDecimal类型),并且在后台对其进行校验,本人在一开始是使用 ( == 0 || equals.(null))对两个参数进行校验,但是发现是无效的。
无效原因:
1、使用 " == " 进行比较
首先BigDecimal不是基本类型,它只是把你的数值(基本类型)封装到了intCompact(Long类型)这个属性中,是对象类型,而只能比较基本类型,所以用“”肯定是不对的。
2、equals()
再说BigDecimal的equals()方法,此方法被其重写了,但并不是像String类一样重写为==,而是

@Override
    public boolean equals(Object x) {
    
    
        if (!(x instanceof BigDecimal))
            return false;
        BigDecimal xDec = (BigDecimal) x;
        if (x == this)
            return true;
        if (scale != xDec.scale)
            return false;
        long s = this.intCompact;
        long xs = xDec.intCompact;
        if (s != INFLATED) {
    
    
            if (xs == INFLATED)
                xs = compactValFor(xDec.intVal);
            return xs == s;
        } else if (xs != INFLATED)
            return xs == compactValFor(this.intVal);
 
        return this.inflated().equals(xDec.inflated());
    }

从源码中可以看到有一个判断scale 值是否相等,scale 这个值是BigDecimal的私有属性,表示BigDecimal小数点位数,所以equals判断两个值是否相等,会先判断这两个数值是否小数点位数是否相等,然后在判断值是否相等。
3、compareTo()方法
采用BigDecimal类的比较方法:compareTo()方法,和BigDecimal.ZERO此固有属性scale为0,故判断结果是否为0,结果为0则相等,否则不等

price1.compareTo(BigDecimal.ZERO)==0

以上。

猜你喜欢

转载自blog.csdn.net/weixin_44653963/article/details/108507232
今日推荐