和BigInteger
类似,BigDecimal
可以表示一个任意大小且精度完全准确的浮点数。
1 2 BigDecimal bd = new BigDecimal("123.4567" ); System.out.println(bd.multiply(bd));
BigDecimal
用scale()
表示小数位数,例如:
1 2 3 4 5 6 BigDecimal d1 = new BigDecimal("123.45" ); BigDecimal d2 = new BigDecimal("123.4500" ); BigDecimal d3 = new BigDecimal("1234500" ); System.out.println(d1.scale()); System.out.println(d2.scale()); System.out.println(d3.scale());
通过BigDecimal
的stripTrailingZeros()
方法,可以将一个BigDecimal
格式化为一个相等的,但去掉了末尾0的BigDecimal
:
1 2 3 4 5 6 7 8 9 BigDecimal d1 = new BigDecimal("123.4500" ); BigDecimal d2 = d1.stripTrailingZeros(); System.out.println(d1.scale()); System.out.println(d2.scale()); BigDecimal d3 = new BigDecimal("1234500" ); BigDecimal d4 = d3.stripTrailingZeros(); System.out.println(d3.scale()); System.out.println(d4.scale());
如果一个BigDecimal
的scale()
返回负数,例如,-2
,表示这个数是个整数,并且末尾有2个0。
可以对一个BigDecimal
设置它的scale
,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.math.BigDecimal;import java.math.RoundingMode;public class Main { public static void main (String[] args) { BigDecimal d1 = new BigDecimal("123.456789" ); BigDecimal d2 = d1.setScale(4 , RoundingMode.HALF_UP); BigDecimal d3 = d1.setScale(4 , RoundingMode.DOWN); System.out.println(d2); System.out.println(d3); } }
对BigDecimal
做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断:
1 2 3 4 BigDecimal d1 = new BigDecimal("123.456" ); BigDecimal d2 = new BigDecimal("23.456789" ); BigDecimal d3 = d1.divide(d2, 10 , RoundingMode.HALF_UP); BigDecimal d4 = d1.divide(d2);
还可以对BigDecimal
做除法的同时求余数:
1 2 3 4 5 6 7 8 9 10 11 import java.math.BigDecimal;public class Main { public static void main (String[] args) { BigDecimal n = new BigDecimal("12.345" ); BigDecimal m = new BigDecimal("0.12" ); BigDecimal[] dr = n.divideAndRemainder(m); System.out.println(dr[0 ]); System.out.println(dr[1 ]); } }
调用divideAndRemainder()
方法时,返回的数组包含两个BigDecimal
,分别是商和余数,其中商总是整数,余数不会大于除数。我们可以利用这个方法判断两个BigDecimal
是否是整数倍数:
1 2 3 4 5 6 BigDecimal n = new BigDecimal("12.75" ); BigDecimal m = new BigDecimal("0.15" ); BigDecimal[] dr = n.divideAndRemainder(m); if (dr[1 ].signum() == 0 ) { }
比较BigDecimal 在比较两个BigDecimal
的值是否相等时,要特别注意,使用equals()
方法不但要求两个BigDecimal
的值相等,还要求它们的scale()
相等:
1 2 3 4 5 BigDecimal d1 = new BigDecimal("123.456" ); BigDecimal d2 = new BigDecimal("123.45600" ); System.out.println(d1.equals(d2)); System.out.println(d1.equals(d2.stripTrailingZeros())); System.out.println(d1.compareTo(d2));
必须使用compareTo()
方法来比较,它根据两个值的大小分别返回负数、正数和0
,分别表示小于、大于和等于。
总是使用compareTo()比较两个BigDecimal的值,不要使用equals()!
如果查看BigDecimal
的源码,可以发现,实际上一个BigDecimal
是通过一个BigInteger
和一个scale
来表示的,即BigInteger
表示一个完整的整数,而scale
表示小数位数:
1 2 3 4 public class BigDecimal extends Number implements Comparable <BigDecimal > { private final BigInteger intVal; private final int scale; }
BigDecimal
也是从Number
继承的,也是不可变对象。
小结 BigDecimal
用于表示精确的小数,常用于财务计算;
比较BigDecimal
的值是否相等,必须使用compareTo()
而不能使用equals()
。