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

 更新时间:2022年12月21日 10:09:24   作者:专注写bug  
BigDecimal属于大数据,精度极高,不属于基本数据类型,属于java对象,下面这篇文章主要给大家介绍了关于Java中BigDecimal与0比较的一个坑的相关资料,需要的朋友可以参考下

前言

在之前做的一个项目中,为了保证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

总结

到此这篇关于Java中BigDecimal与0比较的一个坑的文章就介绍到这了,更多相关Java BigDecimal与0比较内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java Rabbitmq中四种集群架构的区别详解

    Java Rabbitmq中四种集群架构的区别详解

    这篇文章主要为大家详细介绍了Java Rabbitmq中四种集群架构的区别,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • SpringBoot中使用@Value注解注入详解

    SpringBoot中使用@Value注解注入详解

    这篇文章主要介绍了SpringBoot中的@Value注入详解,在SpringBoot中,@Value注解可以注入一些字段的普通属性,并且会自动进行类型转换,本文对这些类型进行总结,需要的朋友可以参考下
    2023-08-08
  • VSCode+Gradle搭建Java开发环境实现

    VSCode+Gradle搭建Java开发环境实现

    这篇文章主要介绍了VSCode+Gradle搭建Java开发环境实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Spring boot注解@Async线程池实例详解

    Spring boot注解@Async线程池实例详解

    这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 基于Mybatis plus 自动代码生成器的实现代码

    基于Mybatis plus 自动代码生成器的实现代码

    本文通过实例代码给大家介绍了基于Mybatis-plus 自动代码生成器的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 学java得这样学,学习确实也得这样

    学java得这样学,学习确实也得这样

    学java得这样学,学习东西确实也得这样
    2008-02-02
  • Maven高级的聚合和继承的实现

    Maven高级的聚合和继承的实现

    在软件开发中,随着项目规模的扩大,单个模块的开发方式逐渐转变为多模块开发,这种方式带来了项目管理上的挑战,其中最常见的问题是模块间的依赖管理和版本控制问题,本文就来介绍一下
    2024-10-10
  • MyBatis-Plus 批量保存的操作方法

    MyBatis-Plus 批量保存的操作方法

    在项目开发中,需要插入批量插入20多万条数据,通过日志观察,发现在调用MyBatis-Plus中的saveBatch()方法性能非常的差,本篇文章主要分享一下saveBatch()的原理以及使用的注意事项,感兴趣的朋友跟随小编一起看看吧
    2024-01-01
  • Springboot整合Urule的方法步骤

    Springboot整合Urule的方法步骤

    这篇文章主要介绍了Springboot整合Urule的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Java EE过滤器优先级控制的实例解读

    Java EE过滤器优先级控制的实例解读

    通过使用@Priority注解,可以控制JavaEE应用中过滤器的执行顺序,在上面的示例中,我们通过设置不同的优先级,实现了TimeFilter和LogFilter的执行顺序控制
    2025-02-02

最新评论