开发者

Java BigDecimal解决double精度丢失的问题

开发者 https://www.devze.com 2023-11-13 10:20 出处:网络 作者: Andy_GF
目录场景BigDecimal 使用创建 BigDecimal 对象计算操作1. 加法 add2. 减法 subtract3. 乘法4. 除法5. 保留小数和舍入模式6. BigDecimal 转化为 double总结我们在日常开发中, 有很多时候会遇到小数(double类型)精确计
目录
  • 场景
  • BigDecimal 使用
    • 创建 BigDecimal 对象
  • 计算操作
    • 1. 加法 add
    • 2. 减法 subtract
    • 3. 乘法
    • 4. 除法
    • 5. 保留小数和舍入模式
    • 6. BigDecimal 转化为 double
  • 总结

    我们在日常开发中, 有很多时候会遇到小数(double类型)精确计算, 由于 double 类型在计算机中的特殊存储方式, 某些情况下会导致精度丢失, 特别是跟钱有关的计算, 后台校验的时候, 那得是分毫不差.

    场景

    商品a价格是 0.1, 商品b 价格是 0.编程2, 用户买了这两个商品, 付款时, 订单总金额是 0.3, 如果用 double 类型做计算, 将会得到结果 0.30000000000000004, 前端如果拿来展示总金额, 用户肯定就蒙圈了, 这显然不是我们想要的.

    那么如何解决呢? Java 给我们js提供了专门解决这个问题的类 BigDecimal.

    double a = 0.1;
    double b = 0.2;
    double c = a + b;
    System.out.println(c); // 0.30000000000000004

    BigDecimal 使用

    创建 BigDecimal 对象

    创建对象一共有3种方式, 两个构造器, 一个静态方法, 实际静态方法是对入参 String 的构造器的封装, 即 2, 3 两种方式本质上是一样的.

     // 1 入参是 double
     BigDecimal a = new BigDecimal(0.3);
     // 2 入参是 String
     BigDecimal b = new BigDecimal("0.3");
     // 3 静态方法, 入参是 double
     BigDecimal c =  BigDecimal.valueOf(0.3);

    计算操作

    公用代码

    double a = 0.1;
    double b = 0.2;
    BigDecimal a1 = BigDecimal.valueOf(a);
    BigDecimal b1 = new BigDecimal(Double.toString(b));

    1. 加法 add

    这就很好的解决了上面场景中出现的问题

    BigDecimal c1 = a1.add(b1);  
    System.out.println(c1); // 0.3

    2. 减法 subtract

    BigDecimal c2 = a1.subtract(b1);  // 减法
    System.out.priwww.devze.comntln(c2); // -0.1

    3. 乘法

    BigDecimal c3 = a1.multiply(b1);  // 乘法
    System.out.println(c3); // 0.02

    4. 除法

    BigDecimal c4 = a1.divide(b1);  // 除法  0.1 / 0.3, 无法除尽, 报错.
    System.out.println(c4); // 0.5
    
    BigDecimal c5 = a1.divide(c1);  // 除法  
    System.out.println(c5); // 0.1 / 0.3, 无法除尽, 报错.
    
    c5 = a1.divide(c1, 2, RoundingMode.HALF_UP);  // 除法  0.1 / 0.3  四舍五入
    System.out.println(c5); // 0.5

    注意:

    BigDecimal 进行除法计算时, 强烈建议使用指定保留小数倍数和舍入模式这个方法, 这样可以避免除不尽造成的异常.

    /**
    * 参数1: 除数
    * 参数2: 保留小数的位数
    * 参数3: 舍入模式
    */
    public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)

    5. 保留小数和舍入模式

    设置保留小数和舍入模式 setScale 方法

    BigDecimal price = new BigDecimal("9编程客栈.936");
    price = price.setScale(2, RoundingMode.HALF_UP); // 2位, 四舍五入
    System.out.println(price); // 9.94

    6. BigDecimal 转化为 double

    编程
    double value = c4.doubleValue();

    总结

    使用 BigDecimal 计算时要注意以下几点:

    • 不建议使用入参是 double 的构造器, 因为它仍然存在精度问题.
    • 强烈建议使用入参是 string 的构造器, 或者使用静态方法 valueOf 创建对象, 才能保证精度.
    • 使用 BigDecimal 做 除法 时, 必须要使用 divide(BigDecimal divisor, int scale, RoundingMode roundingMode), 防止除不尽造成异常.

    到此这篇关于Java BigDecimal解决double精度丢失的问题的文章就介绍到这了,更多相关Java BigDecimal double精度丢失内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消