Java 在 java.math 包中提供的 API 类 BigDecimal,用来对超过16位有效位的数进行精确的运算
提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。
用户能通过提供 MathContext 对象完全控制 BigDecimal 的舍入行为(也可使用类内提供的8种舍入模式)。如果未指定舍入模式,并且无法表示准确结果,则抛出一个异常。
1、构造方法
BigDecimal 一般用如下4个构造方法:
方法名称 | 方法解释 |
BigDecimal(int) | 创建一个具有参数所指定整数值的对象 |
BigDecimal(double) | 创建一个具有参数所指定双精度值的对象。(不建议采用) |
BigDecimal(long) | 创建一个具有参数所指定长整数值的对象 |
BigDecimal(String) | 创建一个具有参数所指定以字符串表示的数值的对象 |
2、加减乘除运算
方法名称 | 方法解释 |
public BigDecimal add(BigDecimal value) | 加法 |
public BigDecimal subtract(BigDecimal value) | 减法 |
public BigDecimal multiply(BigDecimal value) | 乘法 |
public BigDecimal divide(BigDecimal value) | 除法 |
注意: divide 除法需要注意精度,因为存在除不开的情况,这时需要考虑保留位数和舍入模式,需要用到如下方法
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 第一参数表示除数, 第二个参数表示小数点后保留位数,第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式
3、舍入模式
枚举值 | 解释 | 原值 | 保留5位取值 |
RoundingMode.UP | 远离零的舍入模式(向上舍入)。舍弃某部分时,若舍弃部分非零则对其前面的数字加1(此舍入模式始终不会减少计算值的大小) | 0.833333... | 0.83334 |
RoundingMode.DOWN | 接近零的舍入模式(向下舍入)。直接丢弃需舍弃部分(此舍入模式始终不会增加计算值的大小) | 0.833333... | 0.83333 |
RoundingMode.CEILING | 接近正无穷大的舍入模式。若BigDecimal为正,则舍入行为同ROUND_UP;若为负,则舍入行为同ROUND_DOWN(此舍入模式始终不会减少计算值大小) | 0.833333... | 0.83334 |
-0.833333... | -0.83333 | ||
RoundingMode.FLOOR | 接近负无穷大(不是无穷小哦)的舍入模式。其行为与ROUND_CEILING相反,若BigDecimal为负,则舍入行为同ROUND_UP;若为正,则舍入行为同ROUND_DOWN(此舍入模式始终不会增加计算值大小) | 0.833333... | 0.83333 |
-0.833333... | -0.83334 | ||
RoundingMode.HALF_UP | 向最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式(四舍五入,即舍弃部分>=0.5则向上舍入,否则向下舍入) | 0.9166666... | 0.91667 |
0.833333... | 0.83333 | ||
RoundingMode.HALF_DOWN | 向最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向下舍入的舍入模式(舍弃部分<=0.5则向下舍入,否则向上舍入) | 0.9166666.. | 0.91667 |
0.833333... | 0.83333 | ||
RoundingMode.HALF_EVEN | 向最接近的数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入(在重复进行一系列计算时,此舍入模式可以将累加错误减到最小) | 3.3333333... | 3.33333 |
0.9166666... | 0.91667 | ||
RoundingMode.UNNECESSARY | 断言请求的操作具有精确的结枚,因此不需要舍入,若该操作无精确结果(如1/3)则抛出 ArithmeticException | 1 | 1.00000 |
0.333333... | ArithmeticException |
java 的 math 包下 RoundingMode枚举类源码如下
public static RoundingMode valueOf(int rm) {
switch(rm) {
case BigDecimal.ROUND_UP:
return UP;
case BigDecimal.ROUND_DOWN:
return DOWN;
case BigDecimal.ROUND_CEILING:
return CEILING;
case BigDecimal.ROUND_FLOOR:
return FLOOR;
case BigDecimal.ROUND_HALF_UP:
return HALF_UP;
case BigDecimal.ROUND_HALF_DOWN:
return HALF_DOWN;
case BigDecimal.ROUND_HALF_EVEN:
return HALF_EVEN;
case BigDecimal.ROUND_UNNECESSARY:
return UNNECESSARY;
default:
throw new IllegalArgumentException("argument out of range");
}
}
从中可以看出它们的对应关系,如、RoundingMode.UP 与 BigDecimal.ROUND_UP 等价
枚举变量名 | 枚举变量名 | 常量值 |
RoundingMode.UP | BigDecimal.ROUND_UP | 0 |
RoundingMode.DOWN | BigDecimal.ROUND_DOWN | 1 |
RoundingMode.CEILING | BigDecimal.ROUND_CEILING | 2 |
RoundingMode.FLOOR | BigDecimal.ROUND_FLOOR | 3 |
RoundingMode.HALF_UP | BigDecimal.ROUND_HALF_UP | 4 |
RoundingMode.HALF_DOWN | BigDecimal.ROUND_HALF_DOWN | 5 |
RoundingMode.HALF_EVEN | BigDecimal.ROUND_HALF_EVEN | 6 |
RoundingMode.UNNECESSARY | BigDecimal.ROUND_UNNECESSARY | 7 |
4、其他
BigDecimal 可以通过 setScale 方法设置精度及舍入方式
public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
return setScale(newScale, roundingMode.oldMode);
}
5、参考
官方文档 https://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html