Java中BigDecimal与0比较的一个坑实战记录

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Java中BigDecimal与0比较的一个坑实战记录

专注写bug   2022-12-24 我要评论

前言

在之前做的一个项目中,为了保证BigDecimal在除数 divide时,如果被除数为0,出现java.lang.ArithmeticException: / by zero 报错问题,写了一个对比。具体代码如下:

public static BigDecimal getScale(BigDecimal data1,BigDecimal data2,Integer scale){
    if(Objects.isNull(data1) || BigDecimal.ZERO.equals(data1)
        || Objects.isNull(data2) || BigDecimal.ZERO.equals(data2)){
        return BigDecimal.ZERO;
    }
    return data1.divide(data2,scale,BigDecimal.ROUND_HALF_UP);
}

咋一看,的确没毛病。

当被除数为0时,直接由判断返回,并不会进入下面的计算流程。

但,却忽略了一个问题,如果数据是从数据库中查询,数据库中设定的数的格式是0.00时,此时完美绕开了判断。

原因就在于:

new BigDecimal("0.00").equals(BigDecimal.ZERO) 为 false。

问题解决

其实这类问题,很好解决,在BigDecimal源码中,有一个compareTo的方法

简单写个demo,验证效果:

System.out.println(new BigDecimal("0.0").compareTo(BigDecimal.ZERO));
System.out.println(new BigDecimal("0.00").compareTo(BigDecimal.ZERO));
System.out.println(new BigDecimal("0.0000000").compareTo(BigDecimal.ZERO));

System.out.println(new BigDecimal("0").compareTo(BigDecimal.ZERO));

System.out.println(new BigDecimal("0.1").compareTo(BigDecimal.ZERO));

分别打印上面的执行结果,可以发现

不管是什么格式的0,与0相等则返回0;比0大则返回1;比0小则返回-1。

问题讲解

通过compareTo就能解决不同格式的零值,与0使用equals相比为false的问题。

附:Java BigDecimal中一些其他的坑

1.当精度不准确时汇报异常:

代码如下:

BigDecimal a = new BigDecimal("1.2222");
System.out.println(a.setScale(2));

异常如下:

Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
    at java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4148)
    at java.math.BigDecimal.needIncrement(BigDecimal.java:4204)
    at java.math.BigDecimal.divideAndRound(BigDecimal.java:4112)
    at java.math.BigDecimal.setScale(BigDecimal.java:2452)
    at java.math.BigDecimal.setScale(BigDecimal.java:2512)
    at com.hj.demo.test.Test01.main(Test01.java:8)

需要加上第二个参数:

BigDecimal a = new BigDecimal("1.2222");
System.out.println(a.setScale(2,BigDecimal.ROUND_HALF_UP));

运行结果如下:

1.22

2. BigDecimal做除法时如果出现除不尽(循环小数)时汇报异常:

BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
        
System.out.println("a / b =" + a.divide(b));

异常如下:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    at java.math.BigDecimal.divide(BigDecimal.java:1690)
    at com.hj.demo.test.Test01.main(Test01.java:10)

此时应该给予divide第二个和第三个参数用来保留小数位数:

BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("3");
        
System.out.println("a / b =" + a.divide(b,2,BigDecimal.ROUND_HALF_UP));

运行结果如下:

a / b =0.33

总结

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们