使用场景
BigDecimal
用于表示精确的小数,常用于财务计算;
比较BigDecimal
的值是否相等,必须使用compareTo()
而不能使用equals()
。
特征
BigDecimal
是不可变类,每次修改、计算返回的是新对象- 和
BigInteger
类似,BigDecimal
可以表示一个任意大小且精度完全准确的浮点数
加减乘除
- 加法:add()函数
- 减法:subtract()函数
- 乘法:multiply()函数
- 除法:divide()函数
- 绝对值:abs()函数
【注意】!
-
不要使用
double
构造BigDecimal
,会丢失精度,要用String
构造因为此构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 无法准确地表示为double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。
-
如果一定要通过
double
构造对象,可以先Double.toString(double)
得到String,再用String去构造对象
其他方法
scale()
返回小数位数
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("1234500");
System.out.println(d1.scale()); // 2,两位小数
System.out.println(d2.scale()); // 4
System.out.println(d3.scale()); // 0
stripTrailingZeros()
可以将一个
BigDecimal
格式化为一个相等的,但去掉了末尾0的BigDecimal
,如果一个BigDecimal
的scale()
返回负数,例如,-2
,表示这个数是个整数,并且末尾有2个0。
BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();
System.out.println(d1.scale()); // 4
System.out.println(d2.scale()); // 2,因为去掉了00
BigDecimal d3 = new BigDecimal("1234500");
BigDecimal d4 = d3.stripTrailingZeros();
System.out.println(d3.scale()); // 0
System.out.println(d4.scale()); // -2
setScale()
可以对一个
BigDecimal
设置它的scale
,如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断
BigDecimal d1 = new BigDecimal("123.456789");
BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568
BigDecimal d3 = d1.setScale(4, RoundingMode.DOWN); // 直接截断,123.4567
System.out.println(d2);
System.out.println(d3);
divide(d2, 10, RoundingMode.HALF_UP)
对
BigDecimal
做加、减、乘时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时,就必须指定精度以及如何进行截断
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("23.456789");
BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入
BigDecimal d4 = d1.divide(d2); // 报错:ArithmeticException,因为除不尽
divideAndRemainder(BigDecimal m)
可以对
BigDecimal
做除法的同时求余数
BigDecimal n = new BigDecimal("12.345");
BigDecimal m = new BigDecimal("0.12");
BigDecimal[] dr = n.divideAndRemainder(m);
System.out.println(dr[0]); // 102 商
System.out.println(dr[1]); // 0.105 余数
signum()
根据正负返回-1、0、1,返回0表示等于0
-
equals()
与compareTo()
在比较两个
BigDecimal
的值是否相等时,要特别注意,使用equals()
方法不但要求两个BigDecimal
的值相等,还要求它们的scale()
相等;必须使用
compareTo()
方法来比较,它根据两个值的大小分别返回负数、正数和0
,分别表示小于、大于和等于。BigDecimal d1 = new BigDecimal("123.456"); BigDecimal d2 = new BigDecimal("123.45600"); System.out.println(d1.equals(d2)); // false,因为scale不同 System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为3 System.out.println(d1.compareTo(d2)); // 0
总是使用compareTo()比较两个BigDecimal的值,不要使用equals()!