1、概述
位于java.math包中,用于商业计算等高精度运算,用来对超过16位有效位的数进行精确的运算。
对于上述代码的运行结果如下:
可以看出double类型运算会产生一定的误差。原因在于计算机所使用的二进制无法精确表示某些带小数位的十进制数据。比如(0.75)10=(0.11)2,而(0.65)10=(0.101001100110011001100110011001100110011…)2
BigDecimal继承了Number类,实现了Comparable<BigDecimal>接口
在BigDecimal中
scale指的是小数点后的位数。
roundingMode是小数的保留模式。值为BigDecimal中的常量字段。
ROUND_UP:向远离0的方向舍入
ROUND_DOWN:向0方向舍入
ROUND_CEILING:向正无穷方向舍入
ROUND_FLOOR:向负无穷方向舍入
ROUND_HALF_UP:向最近的方向舍入,如果相等,向上舍入
ROUND_HALF_DOWN:向最近的方向舍入,如果相等,向下舍入
ROUND_HALF_EVEN:向最近的方向舍入,如果相等,如果保留位是偶数,则向上舍入,如果是奇数,则向下舍入。
ROUND_UNNECESSARY:计算结果是精确的,不需要舍入模式
2、构造方法
- public BigDecimal(BigInteger)
- public BigDecimal(double)
- public BigDecimal(char[])
- public BigDecimal(long)
- public BigDecimal(String)
- …
使用double转换时是会出现误差的。
jdk1.8 中注释如下
/**
* The results of this constructor can be somewhat unpredictable.
* One might assume that writing {@code new BigDecimal(0.1)} in
* Java creates a {@code BigDecimal} which is exactly equal to
* 0.1 (an unscaled value of 1, with a scale of 1), but it is
* actually equal to
* 0.1000000000000000055511151231257827021181583404541015625.
* This is because 0.1 cannot be represented exactly as a
* {@code double} (or, for that matter, as a binary fraction of
* any finite length). Thus, the value that is being passed
* <i>in</i> to the constructor is not exactly equal to 0.1,
* appearances notwithstanding.
* /
这个构造函数的结果可能是不可预测的。有些人认为new BigDecimal(0.1)正好等于0.1但是它实际上是等
于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1不能精确的表示
为一个双精度的数。
所以这个构造方法是不建议使用的,通常会转换为String类型(即使用Double.toString(double))或者是使用BigDecimal的静态方法valueOf(double),内部实现和前面一样。
3、加减乘除运算
public static void main(String[] args) {
BigDecimal decimal = new BigDecimal("0.12");
BigDecimal decimal1 = new BigDecimal("0.012");
System.out.println(decimal.add(decimal1));
System.out.println(decimal.subtract(decimal1));
System.out.println(decimal.multiply(decimal1));
System.out.println(decimal.divide(decimal1));
}
/*
0.132
0.108
0.00144
1E+1
*/