浅谈Java基础知识之BigDecimal

 更新时间:2021年05月13日 11:01:22   投稿:lan00zi  
我们又来回顾Java基础知识啦,今天讲的是BigDecimal的基本使用以及异常处理,下文中有非常详细的代码示例以及注释哦,需要的朋友可以参考下

一、基本使用

使用示例:

// 初始化
BigDecimal bd1=new BigDecimal("456");
BigDecimal bd2=new BigDecimal("123");

// 加
BigDecimal add=bd1.add(bd2);
// 减
BigDecimal subtract=bd1.subtract(bd2);  
// 乘
BigDecimal multiply=bd1.multiply(bd2); 
// 除
BigDecimal divide=bd1.divide(bd2);     

// 指数运算, 2 is exponent
BigDecimal powerValue=bd2.pow(2);     

// 四舍五入
multiply.setScale(1, RoundingMode.HALF_EVEN);

二、舍入模式

枚举类 java.math.RoundingMode 定义了8种数据的舍入模式,在 BigDecimal 中,可以用 BigDecimal.setScale(int newScale, RoundingMode roundingMode) 来设置数据的精度和舍入模式。

  • ROUND_UP:向远离零的方向舍入。
  • 若舍入位为非零,则对舍入部分的前一位数字加1;若舍入位为零,则直接舍弃。即为向外取整模式。
  • ROUND_DOWN:向接近零的方向舍入。
  • 不论舍入位是否为零,都直接舍弃。即为向内取整模式。
  • ROUND_CEILING:向正无穷大的方向舍入。
  • BigDecimal 为正,则舍入行为与 ROUND_UP 相同;若为负,则舍入行为与 ROUND_DOWN 相同。即为向上取整模式。
  • ROUND_FLOOR:向负无穷大的方向舍入。
  • BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;若为负,则舍入行为与 ROUND_UP 相同。即为向下取整模式。
  • ROUND_HALF_UP:向“最接近的”整数舍入。
  • 若舍入位大于等于5,则对舍入部分的前一位数字加1;若舍入位小于5,则直接舍弃。即为四舍五入模式。
  • ROUND_HALF_DOWN:向“最接近的”整数舍入。
  • 若舍入位大于5,则对舍入部分的前一位数字加1;若舍入位小于等于5,则直接舍弃。即为五舍六入模式。
  • ROUND_HALF_EVEN:向“最接近的”整数舍入。
  • 若(舍入位大于5)或者(舍入位等于5且前一位为奇数),则对舍入部分的前一位数字加1;
  • 若(舍入位小于5)或者(舍入位等于5且前一位为偶数),则直接舍弃。即为银行家舍入模式。
  • ROUND_UNNECESSARY
  • 断言请求的操作具有精确的结果,因此不需要舍入。
  • 如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。

在这里插入图片描述

三、注意事项

1.大量的数学计算时,使用 基本数据类型 而不是BigIntegerBigDecimal

原因:由于是不可变(immutable)的,在进行每一步运算时,都会产生一个新的对象,引起开销。
建议:应尽量用 long , float , double 等基本类型做科学计算或者工程计算。
设计的目的是用来精确地表示大整数和小数,例如进行金额等比较敏感的数据运算。

2.构造 BigDecimal 时,使用 String 而不是 double

原因:有些数字用 double 根本无法精确表示,传给 BigDecimal 构造方法时就已经不精确了。例如:new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。
建议:使用 new BigDecimal(“0.1”) 得到的值是 0.1。
BigDecimal 有4个构造方法,其中的两个用 BigInteger 构造,一个用 double 构造,一个用 String 构造。

3.比较两个 BigDecimal 值时,使用 compareTo() 而不是 equals()

原因: equals() 方法认为 0.1 和 0.1 是相等的,返回true;认为 0.10 和 0.1 是不等的,返回false。
compareTo() 方法则认为 0.1 与 0.1 相等,0.10 与 0.1 也相等。

4.另外还有一些情形,任意精度的小数运算仍不能表示精确结果。例如,1 除以 9 会产生无限循环的小数 .111111…。
出于这个原因,在进行除法运算时,BigDecimal可以让您显式地控制舍入。

四、异常处理 ArithmeticException异常

在使用BigDecimal数据类型进行计算时,会有三种情况抛出 ArithmeticException,分别是:

1.当除数为 0 时,这种情况比较常见,所以我们在进行除法运算之前先判断下除数是否为 0;

2.如果运算的结果是无线循环的小数,并且在除的时候没有对结果设置精确的位数;
BigDecimal divide 方法结果为无限小数问题 10/3=3.3333333333333333…

public static void main(String[] args) {
	BigDecimal a = new BigDecimal("10");
	BigDecimal o = new BigDecimal("3");
	System.out.print(a.divide(o,2, BigDecimal.ROUND_DOWN).doubleValue());
}

Note:不设置精度范围会出现异常

3.当我们设置了结果的舍入模式是 ROUND_UNNECESSARY 模式时:
如果确保了计算的结果是精确的,则不会抛出异常;否则,就会抛出ArithmeticException 异常。

4.只设置精度(小数点后面的位数,scale),但没有设置舍入模式(roundingModel)时,会不知道如何对小数舍入而报错。
所以在设置精度时要连舍入模式一起设置。

// wrong code
 bd = new BigDecimal(1.5); // is actually 1.4999....
 bd.setScale(1); // throws ArithmeticException
 
 // wright code
 a = new BigDecimal("2.5"); // digit left of 5 is even, so round down
 b = new BigDecimal("1.5"); // digit left of 5 is odd, so round up
 a.setScale(0, BigDecimal.ROUND_HALF_EVEN).toString() // => 2
 b.setScale(0, BigDecimal.ROUND_HALF_EVEN).toString() // => 2

5.指数运算,指数 exponent 为负数时
If you are raising things to negative exponents, you must specify a MathContext in BigDecimal.pow(int, MathContext) so it knows how much precision to use – otherwise, BigDecimal will try to compute it to infinite precision, which is not possible for some values.

//wrong code
BigDecimal powerValue=bd2.pow(-27);// -27 is exponent

到此这篇关于浅谈Java基础知识之BigDecimal的文章就介绍到这了,更多相关Java BigDecimal内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于java使用JavaMail发送邮件

    基于java使用JavaMail发送邮件

    这篇文章主要介绍了基于java使用JavaMail发送邮件 ,非常具有实用价值,需要的朋友可以参考下。
    2016-12-12
  • TF-IDF理解及其Java实现代码实例

    TF-IDF理解及其Java实现代码实例

    这篇文章主要介绍了TF-IDF理解及其Java实现代码实例,简单介绍了tfidf算法及其相应公式,然后分享了Java实现代码,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java枚举的使用方法详解

    Java枚举的使用方法详解

    这篇文章主要介绍了 Java枚举的使用方法详解的相关资料,希望通过本文大家能掌握枚举的使用方法,需要的朋友可以参考下
    2017-09-09
  • Java的RTTI和反射机制代码分析

    Java的RTTI和反射机制代码分析

    这篇文章主要涉及了Java的RTTI和反射机制代码分析的相关内容,在介绍运行时类型识别的同时,又向大家展示了其实例以及什么时候会用到反射机制,内容丰富,需要的朋友可以参考下。
    2017-09-09
  • Java网络编程UDP协议发送接收数据

    Java网络编程UDP协议发送接收数据

    这篇文章主要为大家详细介绍了Java网络编程UDP协议发送接收数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java实现截取字符串的操作详解

    Java实现截取字符串的操作详解

    在这篇文章中,小编将带大家一起学习一下在Java中把一个String截断到所需的字符数的几种方法,文中的方法简洁易懂,需要的可以参考一下
    2022-07-07
  • java并发编程关键字volatile保证可见性不保证原子性详解

    java并发编程关键字volatile保证可见性不保证原子性详解

    这篇文章主要为大家介绍了java并发编程关键字volatile保证可见性不保证原子性详解,文中附含详细示例说明,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-02-02
  • 面试必时必问的JVM 类加载机制详解

    面试必时必问的JVM 类加载机制详解

    这篇文章主要介绍了一文读懂Jvm类加载机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2021-08-08
  • MyBatis如何配置多sql脚本执行

    MyBatis如何配置多sql脚本执行

    这篇文章主要介绍了MyBatis如何配置多sql脚本执行问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 解决springboot无法注入JpaRepository的问题

    解决springboot无法注入JpaRepository的问题

    这篇文章主要介绍了解决springboot无法注入JpaRepository的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01

最新评论