提起BigDecimal,相信大家都使用过,之所以总结这篇呢,是因为最近发现项目中使用的不是太规范,在某些场景下甚至出现代码抛出异常的情况,

所以就总结了这篇,希望大家在使用时,可以少踩一些坑。

1. 基本运算

1.1 加法

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.add(number2);
System.out.println("number1 add number2 = " + number3);

输出结果:

number1 add number2 = 100.00

1.2 减法

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.subtract(number2);
System.out.println("number1 subtract number2 = " + number3);

输出结果:

number1 subtract number2 = 77.76

1.3 乘法

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.multiply(number2);
System.out.println("number1 multiply number2 = " + number3);

输出结果:

number1 multiply number2 = 988.3456

1.4 除法

BigDecimal number1 = new BigDecimal("88");
BigDecimal number2 = new BigDecimal("11"); BigDecimal number3 = number1.divide(number2);
System.out.println("number1 divide number2 = " + number3);

输出结果:

number1 divide number2 = 8

因为上面2个数可以整除,所以这么用没有问题,不过一但不能被整除,这么用就会有潜在的风险,会抛出java.lang.ArithmeticException异常,所以强烈建议像下面这样使用

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.divide(number2, 2, RoundingMode.HALF_UP);
System.out.println("number1 divide number2 = " + number3);

输出结果:

number1 divide number2 = 7.99

此时使用的divide()方法源码如下所示:

public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
return divide(divisor, scale, roundingMode.oldMode);
}

这里的scale指的是要保留的小数位数,我们传的是2,即保留2位小数。

这里的roundingMode指的是舍入模式,我们这里传的是RoundingMode.HALF_UP,即经常使用的四舍五入模式。

1.5 保留小数位数

如果我们想对BigDecimal类型保留小数位数,可以使用setScale()方法,使用方法如下所示:

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.multiply(number2);
System.out.println("number1 multiply number2 = " + number3); // 保留3位小数,四舍五入
BigDecimal number4 = number3.setScale(3, RoundingMode.HALF_UP);
System.out.println("number3 setScale = " + number4);

输出结果:

number1 multiply number2 = 988.3456

number3 setScale = 988.346

1.6 比较大小

BigDecimal比较大小,可以使用compareTo()方法,使用方法如下所示:

BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = new BigDecimal("11.11");
BigDecimal number3 = new BigDecimal("99.99");
BigDecimal number4 = new BigDecimal("88.88"); System.out.println("number1 compareTo number2 = " + number1.compareTo(number2));
System.out.println("number1 compareTo number3 = " + number1.compareTo(number3));
System.out.println("number1 compareTo number4 = " + number1.compareTo(number4));

输出结果:

number1 compareTo number2 = 1

number1 compareTo number3 = -1

number1 compareTo number4 = 0

由输出结果可以看出:

当number1小于number2时,返回-1,

当number1等于number2时,返回0,

当number1大于number2时,返回1。

2. 踩坑总结

2.1 NullPointerException异常

在使用BigDecimal类型进行计算时,比如上面提到的加、减、乘、除、比较大小时,一定要保证参与计算的两个值不能为空,否则会抛出java.lang.NullPointerException异常。

比如下面的2段代码,都会抛出异常:

BigDecimal number1 = null;
BigDecimal number2 = new BigDecimal("11.12"); BigDecimal number3 = number1.add(number2);
System.out.println("number1 add number2 = " + number3);
BigDecimal number1 = new BigDecimal("88.88");
BigDecimal number2 = null; BigDecimal number3 = number1.add(number2);
System.out.println("number1 add number2 = " + number3);

抛出的异常如下图所示:

2.2 ArithmeticException异常

一次在使用BigDecimaldivide方法时,抛出java.lang.ArithmeticException异常,错误代码如下所示:

// 含税金额
BigDecimal inclusiveTaxAmount = new BigDecimal("1000");
// 税率
BigDecimal taxRate = new BigDecimal("0.13");
// 不含税金额 = 含税金额 / (1+税率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate)); System.out.println(exclusiveTaxAmount);

运行时抛出以下异常:

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

报错原因是因为无法整除,导致结果是无限循环小数:

解决方案是指定下舍入模式,比如我们最常用的四舍五入模式:

// 不含税金额 = 含税金额 / (1+税率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate),RoundingMode.HALF_UP);

此时不再报错,输出结果为:

885

但这里我的需求是保留2位小数,四舍五入,因此代码应该是下面这样的:

// 不含税金额 = 含税金额 / (1+税率)
BigDecimal exclusiveTaxAmount = inclusiveTaxAmount.divide(BigDecimal.ONE.add(taxRate), 2, RoundingMode.HALF_UP);

此时的输出结果为:

884.96

如果你的IDEA装了阿里巴巴代码规范插件,如果不指定RoundingMode,会有下面这样的提示:

3. 使用规范

尽量不要在项目中使用new BigDecimal("0"),而是使用BigDecimal提供的常量BigDecimal.ZERO

BigDecimal zero = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
BigDecimal ten = BigDecimal.TEN;

Java BigDecimal使用指南的更多相关文章

  1. Java学习笔记(四)——google java编程风格指南(上)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  2. Java学习笔记(五)——google java编程风格指南(中)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  3. Java学习笔记(六)——google java编程风格指南(下)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  4. Java多线程初学者指南系列教程

    转自:http://developer.51cto.com/art/200911/162925.htm 51cto 本系列来自NokiaGuy的“真的有外星人吗”博客,系列名称为<Java多线程 ...

  5. 【Todo】【读书笔记】Java多线程编程指南-设计模式篇

    下了这本书<Java多线程编程指南-设计模式篇>, 还有另一本<JAVA多线程设计模式>,据说内容有重复,结合着看.

  6. Java工程师学习指南 完结篇

    Java工程师学习指南 完结篇 先声明一点,文章里面不会详细到每一步怎么操作,只会提供大致的思路和方向,给大家以启发,如果真的要一步一步指导操作的话,那至少需要一本书的厚度啦. 因为笔者还只是一名在校 ...

  7. Java工程师学习指南 中级篇

    Java工程师学习指南 中级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我写的文章都是站 ...

  8. Java工程师学习指南 初级篇

    Java工程师学习指南 初级篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我之前写的文章都 ...

  9. Java工程师学习指南 入门篇

    Java工程师学习指南 入门篇 最近有很多小伙伴来问我,Java小白如何入门,如何安排学习路线,每一步应该怎么走比较好.原本我以为之前的几篇文章已经可以解决大家的问题了,其实不然,因为我之前写的文章都 ...

随机推荐

  1. P5468 [NOI2019]回家路线 斜率优化 dp

    LINK:回家路线 (文化课 oi 双爆炸 对 没学上的就是我.(我错了不该这么丧的. 不过还能苟住一段时间.当然是去打NOI了 这道题去年同步赛的时候做过.不过这里再次提醒自己要认真仔细的看题目 不 ...

  2. js跳转界面

    js页面跳转大全 所谓的js页面跳转就是利用javesrcipt对打开的页面ULR进行跳转,如我们打开的是A页面,通过javsrcipt脚本就会跳转到B页面.目前很多垃圾站经常用js跳转将正常页面跳转 ...

  3. Python入门看这些,最详细学习书籍推荐

    随着人工智能以及脚本开发火热,Python已经被推上一个非常火热的巅峰! 那么,想要学习Python却又不知道从哪里开始的朋友,看这里呀~ Python在整个编程语言来说,是比较容易上手,而且“见效” ...

  4. 《笨办法学Python 3》python入门书籍推荐|附下载方式

    <笨办法学Python 3>python入门书籍免费下载 内容简介 本书是一本Python入门书,适合对计算机了解不多,没有学过编程,但对编程感兴趣的读者学习使用.这本书以习题的方式引导读 ...

  5. CSS基础知识(上)

    1.创建结构化.语义丰富HTML 语义化标记是优秀HTML文档的基础. 语义化标记意味着在正确的地方使用正确的元素,从而得到有意义的文档. 有意义的文档可以确保尽可能多的人都能够使用. 1.1 ID和 ...

  6. Redis教程——检视阅读

    Redis教程--检视阅读 参考 Redis教程--菜鸟--蓝本--3.2.100 Redis教程--w3c--3.2.100 Redis教程--w3c--Redis开发运维实践指南 Redis教程- ...

  7. 3、Java 对象和类

    1.理解Java中的类和对象 对象: 作为学习计算机专业的很有意思,跟朋友开玩笑说,我有很多对象,没有就new一个.对象可以说是类的实例,通过类的构造方法得到的一个对象实例.它拥有此对象应有的行为与方 ...

  8. PHP基础之排序

    前言 之前简单介绍了流程控制,函数,数组等.有兴趣的可以看看. PHP入门之类型与运算符 PHP入门之流程控制 PHP入门之函数 PHP入门之数组 接下来介绍一下排序,排序是将一组数据,依指定的顺序进 ...

  9. 新司机的致胜法宝,使用ApexSql Log2018快速恢复数据库被删除的数据

    作为开发人员,误操作数据delete.update.insert是最正常不过的了,比如: 删除忘记加where条件: 查询为了图方便按了F5,但是数据里面夹杂着delete语句. 不管是打着后发动机声 ...

  10. NMS系列

    NMS soft NMS softer NMS https://www.cnblogs.com/VincentLee/p/12579756.html