Java BigDecimal 详解
一、概述
BigDecimal
是Java在java.math
包中提供的线程安全的API类,用来对超过16位有效位的数进行精确的运算。因为Double
和Float
会丢失精度,所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。
BigDecimal
所创建的是对象
,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
二、构造方法
BigDecimal的构造方法比较多,但常见的如下表格
方法 | 解释 |
---|---|
BigDecimal(String val) | 将字符串 转换为BigDecimal (推荐使用) |
BigDecimal(int val) | 将int 转换为BigDecimal |
BigDecimal(long val) | 将long 转换为BigDecimal |
BigDecimal(BigInteger val) | 将BigInteger 转换为BigDecimal |
BigDecimal(double val) | 将double 转换为BigDecimal (不推荐,因为存在精度丢失问题) |
三、常用方法
1. 加法(add)
两个BigDecimal
对象进行相加,返回新的一个BigDecimal
对象,原来加数的值不变。
BigDecimal a = new BigDecimal("1.44444");
BigDecimal b = new BigDecimal("1.33333");
System.out.println(a.add(b));
System.out.println(a);
输出如下:
2.77777
1.44444
2. 减法(subtract)
BigDecimal a = new BigDecimal("1.44444")
BigDecimal b = new BigDecimal("1.33333")
System.out.println(a.subtract(b));
System.out.println(a);
输出如下:
0.11111
1.44444
3. 乘法(multiply)
BigDecimal a = new BigDecimal("1.44444");
BigDecimal b = new BigDecimal("1.33333");
System.out.println(a.multiply(b));
System.out.println(a.multiply(b, new MathContext(5, RoundingMode.HALF_UP))); //设置精度为5位
System.out.println(a.multiply(b).setScale(5, RoundingMode.HALF_UP)); //设置小数点为5位
输出如下:
1.9259151852
1.9259
1.92592
4. 除法(divide)
BigDecimal a = new BigDecimal("1.44444");
BigDecimal b = new BigDecimal("1.33333");
System.out.println(a.divide(b, 4, RoundingMode.HALF_UP)); // 设置小数点为4位
输出如下:
1.0833
5. 取整
BigDecimal a = new BigDecimal("100.11");
BigDecimal b = new BigDecimal("50");
System.out.println(a.divideToIntegralValue(b));
输出如下:
2.00
6. 取余
BigDecimal a = new BigDecimal("100.11");
BigDecimal b = new BigDecimal("50");
System.out.println(a.remainder(b));
输出如下:
0.11
7. 求和
List<BigDecimal> nums = new LinkedList<>();
nums.add(new BigDecimal(-1));
nums.add(new BigDecimal(-1));
nums.add(new BigDecimal(-3));
Optional<BigDecimal> bigDecimal = nums.stream().reduce(BigDecimal::add);
System.out.println(bigDecimal.get()); //-5
8. 最大值、最小值
BigDecimal max = nums.stream().reduce(nums.get(0), BigDecimal::max);
System.out.println(max); //-1
BigDecimal min = nums.stream().reduce(nums.get(0), BigDecimal::min);
System.out.println(min); //-3
9. 比较大小
BigDecimal
的equals
方法,其实不只是会比较数字的值,还会对其标度进行比较,是极其严格的。BigDecimal
的compareTo
方法,只比较值,其中返回结果:-1表示小于,0表示等于,1表示大于。
BigDecimal a = new BigDecimal("-1.00");
BigDecimal b = new BigDecimal("-1.0");
BigDecimal c = new BigDecimal(-3);
System.out.println(a.compareTo(b));
System.out.println(c.compareTo(b));
System.out.println(b.compareTo(c));
System.out.println(a.equals(b)); // equals是极其严格的
0
-1
1
false
10. 设置精度
BigDecimal a = new BigDecimal("1.234567");
System.out.println(a.setScale(3, RoundingMode.HALF_UP)); //常用的四舍五入
四、格式化
BigDecimal a = new BigDecimal("2.335");
BigDecimal b = new BigDecimal("0.035757");
NumberFormat percent = NumberFormat.getPercentInstance(); //建立百分比格式化引用
percent.setMaximumFractionDigits(3); //百分比小数点最多3位
System.out.println("a利率:\t" + percent.format(a));
System.out.println("b利率:\t" + percent.format(b));
a利率: 233.5%
b利率: 3.576%
五、注意点
1. NULL值不能参加计算
在使用BigDecimal类型进行计算时,进行加、减、乘、除、比较大小时,一定要保证参与计算的两个值不能为空,否则会抛出java.lang.NullPointerException异常。
BigDecimal b1 = new BigDecimal("1");
BigDecimal b2 = null;
System.out.println("相加:"+b2.add(b1)); //抛异常
2. 等值比较的坑
不要用==或者equals比较BigDecimal的值,equals
方法,其实不只是会比较数字的值,还会对其标度进行比较,是极其严格的。
尤其当用字符串转BigDecimal对象后,千万不要用equals,容易有坑。所以最好用compareTo
方法。