构造函数

  • 参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。

  • 另一方面,String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。

  • 当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)方法,然后使用BigDecimal(String)构造方法,将double转换为String。要获取该结果,请使用static valueOf(double)方法。

运算

  • 减乘除其实最终都返回的是一个新的BigDecimal对象,因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以a.add(b);虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b);

精度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BigDecimal.setScale() 方法用于格式化小数点

setScale(1) 表示保留一位小数,默认用四舍五入方式

setScale(1,BigDecimal.ROUND_DOWN) 直接删除多余的小数位,2.31变成2.32.35会变成2.3

setScale(1,BigDecimal.ROUND_UP) 进位处理,2.31变成2.4 2.35变成2.4

setScale(1,BigDecimal.ROUND_CEILING) 如果为正数,则舍入行为与 ROUND_UP 相同,反之舍入行为与 ROUND_DOWN 相同

setScale(1,BigDecimal.ROUND_FLOOR) 如果为正数,则舍入行为与 ROUND_DOWN 相同,反之舍入行为与 ROUND_UP 相同

setScale(1,BigDecimal.ROUND_HALF_UP) 四舍五入,2.35变成2.4

setScale(1,BigDecimal.ROUND_HALF_DOWN) 四舍五入,2.35变成2.3(如果是5则向下舍),2.36变成2.4

setScale(1,BigDecimal.ROUND_HALF_EVEN) 银行家舍入法 如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同 如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。如 1.15>1.2 1.25>1.2

异常处理

foo.divide(bar)); 报异常

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

原因:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
原来JAVA中如果用BigDecimal做除法的时候一定要在divide方法中传递第二个参数,定义精确到小数点后几位,否则在不整除的情况下,结果是无限循环小数时,就会抛出以上异常。
解决方法:

foo.divide(bar, 2, BigDecimal.ROUND_HALF_UP);
注意这个divide方法有两个重载的方法,一个是传两个参数的,一个是传三个参数的:

两个参数的方法:

@param divisor value by which this {@code BigDecimal} is to be divided. 传入除数

@param roundingMode rounding mode to apply. 传入round的模式

三个参数的方法:

@param divisor value by which this {@code BigDecimal} is to be divided. 传入除数
@param scale scale of the {@code BigDecimal} quotient to be returned. 传入精度
@param roundingMode rounding mode to apply. 传入round的模式