BigDecimal

152 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

节后第一天,真的有点顶不住,眩晕 :) 想着还是得来肝(shui)一篇,今天就先不整理 FIX 协议了,因为今天在梳理项目逻辑时,碰到了之前没接触过的一些小数的处理方式,一时间有点懵,先总结一下这个......

含义

BigDecimal 是 Java 小数操作的一个专有类,在电商、金融行业存储有关金额的字段。

加减乘除

    public void decimalDemo() {
        BigDecimal a = new BigDecimal(5);
        BigDecimal b = new BigDecimal(40);
        
        BigDecimal add = a.add(b); //加
        BigDecimal subtract = a.subtract(b); //减
        BigDecimal multiply = a.multiply(b); //乘
        BigDecimal divide = a.divide(b); //除
        
        System.out.println("add(a + b):" + add); //45
        System.out.println("subtract(a - b):" + subtract); //-35
        System.out.println("multiply(a * b):" + multiply); //200
        System.out.println("divide(a / b):" + divide); //0.125
     }

精度控制

小数取整

    // 正无穷大方向取整
    new BigDecimal(0.125, new MathContext(2, RoundingMode.CEILING)); //0.13
    
    // 负无穷大方向取整
    new BigDecimal(0.125, new MathContext(2, RoundingMode.FLOOR)); //0.12
    
    //向 0 的方向取整
    new BigDecimal(0.121, new MathContext(2, RoundingMode.DOWN)); //0.12
    new BigDecimal(-0.129, new MathContext(2, RoundingMode.DOWN)); //-0.12
    
    // 正数向正无穷大取整,负数向负无穷大取整
    new BigDecimal(0.121, new MathContext(2, RoundingMode.UP)); //0.13
    new BigDecimal(-0.129, new MathContext(2, RoundingMode.UP)); //-0.13

四舍五入

    /**
      * 5,6,7,8,9 向上取整
      * 1,2,3,4 向下取整
      *
      * 常用的4舍5入
      */
    new BigDecimal(0.125, new MathContext(2, RoundingMode.HALF_UP)); //0.13
    
     /**
      *  6,7,8,9 向上取整
      *  1,2,3,4,5 向下取整
      *
      *  5 向下取整
      */
    new BigDecimal(0.125, new MathContext(2, RoundingMode.HALF_DOWN)); //0.12

     /**
      * 小数位是5时,判断整数部分是奇数就进位
      * 1,2,3,4,  舍弃
      * 6,7,8,9,  进位
      */
    new BigDecimal(5.4, new MathContext(1, RoundingMode.HALF_EVEN)); //5
    new BigDecimal(5.5, new MathContext(1, RoundingMode.HALF_EVEN)); //6
    
     /**
      * 小数位是5时,判断整数部分是偶数就舍弃
      * 1,2,3,4,  舍弃
      * 6,7,8,9,  进位
      */
    new BigDecimal(6.5, new MathContext(1, RoundingMode.HALF_EVEN)); //6
    new BigDecimal(6.6, new MathContext(1, RoundingMode.HALF_EVEN)); //7

总结

模式描述
CEILING正无穷大方向取整
FLOOR负无穷大方向取整
DOWN向 0 的方向取整
UP正数向正无穷大取整,负数向负无穷大取整
HALF_UP5,6,7,8,9 向上取整、 1,2,3,4 向下取整、 常用的4舍5入
HALF_DOWN6,7,8,9 向上取整 1,2,3,4,5 向下取整
HALF_EVEN小数位是5时,判断整数部分是奇数就进位、 小数位是5时,判断整数部分是偶数就舍弃、 1,2,3,4, 舍弃、 6,7,8,9, 进位

BigDecimal.setScale

  • ROUND_DOWN
    new BigDecimal(“2.225667”).setScale(2, BigDecimal.ROUND_DOWN);
    结果:2.22,直接去掉多余的位数

  • ROUND_UP
    new BigDecimal(“2.224667”).setScale(2, BigDecimal.ROUND_UP);
    结果:2.23,跟上面相反,进位处理

  • ROUND_CEILING
    天花板(向上),正数进位向上,负数舍位向上

    new BigDecimal(“2.224667”).setScale(2, BigDecimal.ROUND_CEILING);
    结果:2.23,如果是正数,相当于BigDecimal.ROUND_UP

    new BigDecimal("-2.225667").setScale(2, BigDecimal.ROUND_CEILING);
    结果:-2.22,如果是负数,相当于BigDecimal.ROUND_DOWN

  • ROUND_FLOOR
    地板(向下),正数舍位向下,负数进位向下

    new BigDecimal(“2.225667”).setScale(2, BigDecimal.ROUND_FLOOR);
    结果:2.22,如果是正数,相当于BigDecimal.ROUND_DOWN

    new BigDecimal("-2.224667").setScale(2, BigDecimal.ROUND_FLOOR);
    结果:-2.23,如果是负数,相当于BigDecimal.ROUND_HALF_UP

  • ROUND_HALF_UP new BigDecimal(“2.225”).setScale(2, BigDecimal.ROUND_HALF_UP);
    结果:2.23,四舍五入(若舍弃部分 >= .5,就进位)

  • ROUND_HALF_DOWN
    new BigDecimal(“2.225”).setScale(2, BigDecimal.ROUND_HALF_DOWN);
    结果:2.22,四舍五入(若舍弃部分 > .5,就进位)

  • ROUND_HALF_EVEN
    银行家舍入法
    (1)被修约的数字小于5时,该数字舍去;
    (2)被修约的数字大于5时,则进位;
    (3)被修约的数字等于5时,要看5前面的数字,若是奇数则进位,若是偶数则将5舍掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进位。
    即:四舍六入五考虑,五后非空就进一,五后为空看奇偶,五前为偶应舍去,五前为奇要进一

  • ROUND_UNNECESSARY
    new BigDecimal(“2.215”).setScale(3, BigDecimal.ROUND_UNNECESSARY);
    //断言请求的操作具有精确的结果,因此不需要舍入。

大致总结了一下今天遇到的有关 BigDecimal 的用法,因为今天在看代码时,关于代码中的精度总是分不清,遇到一个就查一下,遇到一个就查一下......
希望本文能够帮到你,如有错误,望指正!
我向你敬礼啊,Salute!