天天看点

BigDecimal用法

前言:

  1. 在计算有小数的参数中,float 、double 会有丢失精度的可能性,因此对于精度比较敏感的参数,例如金钱之类的常使用BigDecimal。
  2. 看一下下面的例子:
public static void main(String[] args) {
        Float f1 = 100.12f;
        Float f2 = 30.03f;
        System.out.println("f1 - f2 = " + (f1 - f2));

        Double d1 = 100.12;
        Double d2 = 30.04;
        System.out.println("d1 - d2 = " + (d1 - d2));
}
           

打印结果:

f1 - f2 = 70.090004
d1 - d2 = 70.08000000000001
           
  1. 解释: float和double都是浮点数, 通过二进制保存数据,由于小数转化为二进制时,会存在无线循环的二进制,但是float和double有精度范围,因此在小数的计算中往往会出现结果不可预判,当在计算金额必须是完全精确的计算, 故不能使用double或者float, 而应该采用java.math.BigDecimal

BigDecimal 的加减乘除:

  1. 加减乘除方法分别是 add、subtract、multiply、divide
  2. 除法需要定义保留的小数位和规则,否则当计算结果无限时,可能会报错。
public static void main(String[] args) {
        // 须使用String类型的字符串,如果直接使用 100.12,会认为float类型,计算之前就已经丢失精度
        BigDecimal big1 = new BigDecimal("100.12");
        BigDecimal big2 = new BigDecimal("30.03");
        // 加法: 130.15
        System.out.println(big1.add(big2));
        // 减法:70.09
        System.out.println(big1.subtract(big2));
        // 乘法:3006.6036
        System.out.println(big1.multiply(big2));
        // 除法,保留两位小数: 3.33
        System.out.println(big1.divide(big2,2,BigDecimal.ROUND_DOWN));
    }

           

BigDecimal 的小数的取舍:

  1. 较为常用的有:

    BigDecimal.ROUND_DOWN: 丢弃多余的小数。

    BigDecimal.ROUND_UP: 多余的小数大约 0 则进位。

    BigDecimal.ROUND_HALF_DOWN : 四舍五入, 剩余的小数 <= 5 则丢弃

    BigDecimal.ROUND_HALF_UP: 四舍五入, 剩余的小数 >= 5 则进位

  2. 参数可以用于 setScale 和 除法 需要定义保存的小数位。

代码示例:

public static void main(String[] args) {
        /**
         *  规则: 保留两位小数,多余的小数舍弃
         *  分析:无
         *  结果: 100.12
         */
        System.out.println(new BigDecimal("100.12101").setScale(2,BigDecimal.ROUND_DOWN));

        /**
         * 规则: 保留两位小数,其他小数 >0则进位
         * 分析:  保留两位小数后,剩余小数 1.01 > 0 所以进位
         * 结果: 100.13
         */
        System.out.println(new BigDecimal("100.12101").setScale(2,BigDecimal.ROUND_UP));

        /**
         *  ROUND_HALF_DOWN 情况一:
         * 规则: 保留两位小数,其他小数 <=5 则舍弃
         * 分析:保留两位小数后,剩余小数 5.0 = 5 所以舍弃
         * 结果:100.12
         */
        System.out.println(new BigDecimal("100.1250").setScale(2,BigDecimal.ROUND_HALF_DOWN));

        /**
         * ROUND_HALF_DOWN 情况二:
         * 分析:保留两位小数后,剩余小数 5.1 > 5 所以进位
         * 结果:100.13
         */
        System.out.println(new BigDecimal("100.1251").setScale(2,BigDecimal.ROUND_HALF_DOWN));

        /**
         * 规则:保留两位小数,其他小数 >=5 进位
         * 分析:保留两位小数后,剩余小数 5.0 >= 5 所以进位
         * 结果:100.13
         */
        System.out.println(new BigDecimal("100.1250").setScale(2,BigDecimal.ROUND_HALF_UP));
    }
    
           

BigDecimal 比较大小:

BigDecimal 比较通过 compareTo 来比较大小,

结果: 0 相等、 1 前者大于后者、-1 前者小于后者

例:

public static void main(String[] args) throws ParseException {
        BigDecimal big = new BigDecimal(100.13);
        BigDecimal small = new BigDecimal(50.13);
        // 等于  0
        System.out.println(big.compareTo(big));
        // 大于 1
        System.out.println(big.compareTo(small));
        // 小于 -1
        System.out.println(small.compareTo(big));
    }

           

BigDecimal 格式化:

一般使用 DecimalFormat,参数类型为格式化后的类型,简单例子:

public class Test {

    public static void main(String[] args) throws Exception{
        DecimalFormat df = new DecimalFormat("#0.00");
        BigDecimal bg = new BigDecimal(1.2353);

        System.out.println(df.format(bg));
        System.out.println(df.format(1.2353));

    }
}

           

打印结果:

BigDecimal用法

小结:

好处: BigDecimal 处理数据可以根据自己的需要获得准确的值

缺点:BigDecimal的性能比double和float差,在处理庞大,复杂的运算时尤为明显,因根据实际需求决定使用哪种类型。

End !!!