BigDecimal 使用总结
工作中很多情况下需要进行精确的小数运算,,在 Java 中使用 float 和 double 这两种浮点数类型进行小数运算时,往往很难达到令人满意的效果,小数点后面总是存在很多位的小数,看起来令人费解,因此不推荐使用这两种浮点数类型进行小数运算。BigDecimal 就是专门用来进行精确计算的,使用起来也非常方便,下面我们就通过代码一起看一下吧。
一、运算效果对比
先给出代码和运算结果,然后再进行结论总结。
package com.jobs;
import java.math.BigDecimal;
public class Demo1 {
public static void main(String[] args) {
double f1 = 0.1;
double f2 = 0.2;
double result1 = f1 + f2;
System.out.println("Double相加的结果:" );
System.out.println(result1);
System.out.println("-----------------");
//使用浮点数初始化BigDecimal
BigDecimal bd1 = new BigDecimal(0.1);
BigDecimal bd2 = new BigDecimal(0.2);
BigDecimal result2 = bd1.add(bd2);
System.out.println("浮点数初始化的BigDecimal相加的结果:");
System.out.println(result2);
System.out.println("-----------------");
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4 = new BigDecimal("0.2");
BigDecimal result3 = bd3.add(bd4);
System.out.println("字符串初始化的BigDecimal相加的结果:");
System.out.println(result3);
}
}
执行的结果是:
从上面的执行结果,可以看出:
【double 类型的小数】和【使用浮点数初始化的 BigDecimal 】在进行小数运算后,结果并不是我们所期望的,甚至【使用浮点数初始化的 BigDecimal 小数】进行小数运算的结果,更加令人感到不爽。
【使用字符串初始化的 BigDecimal 】进行小数运算后的结果,是我们所期望的结果,因此后续尽量使用字符串来初始化 BigDecimal 。
二、BigDecimal 运算示例
还是先给出代码,再总结结论吧:
package com.jobs;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Demo2 {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal("10");
BigDecimal bd2 = new BigDecimal("3");
//相加
BigDecimal add = bd1.add(bd2);
System.out.println("10/3 相加的结果:" + add);
//相减
BigDecimal subtract = bd1.subtract(bd2);
System.out.println("10/3 相减的结果:" + subtract);
//相乘
BigDecimal multiply = bd1.multiply(bd2);
System.out.println("10/3 相乘的结果:" + multiply);
//相除(如果能够除尽,则一切正常)
BigDecimal divide = bd2.divide(bd1);
System.out.println("3/10 相除的结果:" + divide);
//相除(如果除不尽,则抛异常)
//原因:BigDecimal属于精确计算,如果除不尽,必须指定舍入规则
BigDecimal divide0 = bd1.divide(bd2);
System.out.println("10/3 相除的结果:" + divide0);
}
}
执行的结果是:
从执行的结果,可以看出:
【使用字符串初始化的 BigDecimal 】在进行除法运算时,如果能够除尽的话,代码运行就正常,如果除不尽的话,就会抛出异常。原因就是 BigDecimal 属于精确运算,如果除不尽的话,必须要指定小数的舍入规则,这样才能确保运算的结果是我们预期的结果。
三、常用的小数舍入规则
系统提供了很多小数舍入规则,我们常用的也就是 3 种舍入规则:
- RoundingMode.UP 进一法
- RoundingMode.FLOOR 去尾法
- RoundingMode.HALF_UP 四舍五入
package com.jobs;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Demo2 {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal("10");
BigDecimal bd2 = new BigDecimal("3");
//常用的三个舍入规则为:
//RoundingMode.UP 进一法
//RoundingMode.FLOOR 去尾法
//RoundingMode.HALF_UP 四舍五入
System.out.println("相除精确2位小数:");
BigDecimal divide1 = bd1.divide(bd2, 2, RoundingMode.UP);
System.out.println("10/3 小数第3位进1的结果:" + divide1);
BigDecimal divide2 = bd1.divide(bd2, 2, RoundingMode.FLOOR);
System.out.println("10/3 小数第3位舍去的结果:" + divide2);
BigDecimal divide3 = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
System.out.println("10/3 小数第3位四舍五入的结果:" + divide3);
BigDecimal bd3 = new BigDecimal("0.1");
BigDecimal bd4 = new BigDecimal("4");
BigDecimal divide4 = bd3.divide(bd4, 2, RoundingMode.HALF_UP);
System.out.println("0.1/4 实际结果是 0.025,小数第3位四舍五入的结果:" + divide4);
}
}
执行结果如下:
以上就是三种舍入规则的效果演示,平时使用最多的应该还是四舍五入。我们在使用 BigDecimal 进行除法运算时,尽量指定要保留的小数位数,以及舍入规则,否则就会有除不尽导致代码执行过程中抛异常的风险。
Ok,到此为止,有关 BigDecimal 的基本使用,已经介绍的差不多了,相关的示例代码下载地址如下:
https://files.cnblogs.com/files/blogs/699532/BigDecimalDemo.zip