1、是什么?
不可变的,任意精度的带符号十进制数。 A BigDecimal由任意精度整数非标度值和32位整数标度组成 。 如果为零或正数,则比例是小数点右侧的位数。 如果是负数,则将数字的未缩放值乘以10来表示比例的否定。
2、静态方法
变量和类型 | 方法 | 描述 |
---|---|---|
static BigDecimal | valueOf(double val) | 转换一个 double成 BigDecimal ,使用 double通过所提供的规范的字符串表示 Double.toString(double)方法。 |
static BigDecimal | valueOf(long val) | 将 long值转换为 BigDecimal ,其标度为零。 |
static BigDecimal | valueOf(long unscaledVal, int scale) | 将 long值和 int比例转换为 BigDecimal 。 |
3、接口方法
变量和类型 | 方法 | 描述 |
---|---|---|
BigDecimal | abs() | 返回 BigDecimal其值是此的绝对值 BigDecimal ,其标为 this.scale() 。 |
BigDecimal | abs(MathContext mc) | 返回 BigDecimal其值为此 BigDecimal的绝对值,并根据上下文设置进行舍入。 |
BigDecimal | add(BigDecimal augend) | 返回 BigDecimal其值为 (this + augend) ,其比例为 max(this.scale(), augend.scale()) 。 |
BigDecimal | add(BigDecimal augend, MathContext mc) | 返回 BigDecimal其值为 (this + augend) ,根据上下文设置进行舍入。 |
byte | byteValueExact() | 将 BigDecimal转换为 byte ,检查是否丢失了信息。 |
int | compareTo(BigDecimal val) | 将此 BigDecimal与指定的 BigDecimal 。 |
BigDecimal | divide(BigDecimal divisor) | 返回BigDecimal其值为(this / divisor) ,其首选比例为(this.scale() - divisor.scale()) ; 如果无法表示准确的商(因为它具有非终止的十进制扩展),则抛出ArithmeticException 。 |
BigDecimal | divide(BigDecimal divisor, int roundingMode) | 已过时。应该优先使用方法divide(BigDecimal, RoundingMode) ,而不是这种传统方法。 |
BigDecimal | divide(BigDecimal divisor, int scale, int roundingMode) | 已过时。应该优先使用方法divide(BigDecimal, int, RoundingMode)来使用该传统方法。 |
BigDecimal | divide(BigDecimal divisor, int scale, RoundingMode roundingMode) | 返回 BigDecimal其值为 (this / divisor) ,其比例为指定的比例。 |
BigDecimal | divide(BigDecimal divisor, MathContext mc) | 返回 BigDecimal其值为 (this / divisor) ,根据上下文设置进行舍入。 |
BigDecimal | divide(BigDecimal divisor, RoundingMode roundingMode) | 返回 BigDecimal其值为 (this / divisor) ,其比例为 this.scale() 。 |
BigDecimal[] | divideAndRemainder(BigDecimal divisor) | 返回一个两元件 BigDecimal阵列含有的结果 divideToIntegralValue ,随后的结果 remainder上的两个操作数。 |
BigDecimal[] | divideAndRemainder(BigDecimal divisor, MathContext mc) | 返回一个两元件 BigDecimal阵列含有的结果 divideToIntegralValue ,随后的结果 remainder上与根据上下文设置进行舍入计算出的两个操作数。 |
BigDecimal | divideToIntegralValue(BigDecimal divisor) | 返回 BigDecimal其值是 (this / divisor)舍入的商 (this / divisor)的整数部分。 |
BigDecimal | divideToIntegralValue(BigDecimal divisor, MathContext mc) | 返回 BigDecimal ,其值是整数部分 (this / divisor) 。 |
double | doubleValue() | 将 BigDecimal转换为 double 。 |
boolean | equals(Object x) | 将此 BigDecimal与指定的 Object进行相等性比较。 |
float | floatValue() | 将 BigDecimal转换为 float 。 |
int | hashCode() | 返回此 BigDecimal的哈希码。 |
int | intValue() | 将 BigDecimal成 int 。 |
int | intValueExact() | 将 BigDecimal转换为 int ,检查是否丢失了信息。 |
long | longValue() | 将 BigDecimal转换为 long 。 |
long | longValueExact() | 将此 BigDecimal转换为 long ,检查是否丢失了信息。 |
BigDecimal | max(BigDecimal val) | 返回 BigDecimal和 val 。 |
BigDecimal | min(BigDecimal val) | 返回 BigDecimal和 val 。 |
BigDecimal | movePointLeft(int n) | 返回一个 BigDecimal ,相当于这个小数点向左移动 n位置。 |
BigDecimal | movePointRight(int n) | 返回一个 BigDecimal ,相当于这个小数点向右移动 n位置。 |
BigDecimal | multiply(BigDecimal multiplicand) | 返回 BigDecimal其值为 (this × multiplicand) ,其比例为 (this.scale() + multiplicand.scale()) 。 |
BigDecimal | multiply(BigDecimal multiplicand, MathContext mc) | 返回 BigDecimal其值为 (this × multiplicand) ,根据上下文设置进行舍入。 |
BigDecimal | negate() | 返回 BigDecimal其值为 (-this) ,其比例为 this.scale() 。 |
BigDecimal | negate(MathContext mc) | 返回 BigDecimal其值为 (-this) ,根据上下文设置进行舍入。 |
BigDecimal | plus() | 返回 BigDecimal其值为 (+this) ,其比例为 this.scale() 。 |
BigDecimal | plus(MathContext mc) | 返回 BigDecimal其值为 (+this) ,根据上下文设置进行舍入。 |
BigDecimal | pow(int n) | 返回 BigDecimal其值为 (thisn) ,精确计算功率,精度无限制。 |
BigDecimal | pow(int n, MathContext mc) | 返回 BigDecimal其值为 (thisn) 。 |
int | precision() | 返回此 BigDecimal的 精度 。 |
BigDecimal | remainder(BigDecimal divisor) | 返回 BigDecimal其值为 (this % divisor) 。 |
BigDecimal | remainder(BigDecimal divisor, MathContext mc) | 返回 BigDecimal其值为 (this % divisor) ,根据上下文设置进行舍入。 |
BigDecimal | round(MathContext mc) | 返回 BigDecimal根据四舍五入 MathContext设置。 |
int | scale() | 返回 BigDecimal的 比例 。 |
BigDecimal | scaleByPowerOfTen(int n) | 返回其数值等于( this * 10 n )的BigDecimal。 |
BigDecimal | setScale(int newScale) | 返回 BigDecimal其标度为指定值,其值在数值上等于此 BigDecimal 。 |
BigDecimal | setScale(int newScale, int roundingMode) | 已过时。应该优先使用方法setScale(int, RoundingMode)来使用该传统方法。 |
BigDecimal | setScale(int newScale, RoundingMode roundingMode) | 返回 BigDecimal其比例为指定值,其未缩放值通过将此 BigDecimal值乘以或除以适当的10的幂来确定,以保持其总值。 |
short | shortValueExact() | 将此 BigDecimal转换为 short ,检查是否丢失了信息。 |
int | signum() | 返回此 BigDecimal的signum函数。 |
BigDecimal | sqrt(MathContext mc) | 返回 this平方根的 this并根据上下文设置进行舍入。 |
BigDecimal | stripTrailingZeros() | 返回 BigDecimal ,它在数值上等于此值,但从表示中删除了任何尾随零。 |
BigDecimal | subtract(BigDecimal subtrahend) | 返回 BigDecimal其值为 (this - subtrahend) ,其比例为 max(this.scale(), subtrahend.scale()) 。 |
BigDecimal | subtract(BigDecimal subtrahend, MathContext mc) | 返回 BigDecimal其值为 (this - subtrahend) ,根据上下文设置进行舍入。 |
BigInteger | toBigInteger() | 将 BigDecimal转换为 BigInteger 。 |
BigInteger | toBigIntegerExact() | 将 BigDecimal转换为 BigInteger ,检查是否丢失了信息。 |
String | toEngineeringString() | 如果需要指数,则使用工程符号返回此 BigDecimal的字符串表示形式。 |
String | toPlainString() | 返回此 BigDecimal的字符串表示形式,不带指数字段。 |
String | toString() | 如果需要指数,则使用科学计数法返回此 BigDecimal的字符串表示形式。 |
BigDecimal | ulp() | 返回此 BigDecimal的ulp(最后一个单位)的 BigDecimal 。 |
BigInteger | unscaledValue() | 返回 BigInteger其值是此的 非标度值 BigDecimal 。 |
4、加减乘除
static void testFun() {
BigDecimal bd1 = new BigDecimal("12.34");
BigDecimal bd2 = new BigDecimal("56.78");
System.out.println("相加:"+bd1.add(bd2)); // 相加:69.12
System.out.println("相减:"+bd1.subtract(bd2));// 相减:-44.44
System.out.println("相乘:"+bd1.multiply(bd2));// 相乘:700.6652
System.out.println("相除:"+ new BigDecimal(2).divide(new BigDecimal(1))); // 相除:2
System.out.println("相除:"+bd1.divide(bd2)); // 不能整除 Non-terminating decimal expansion; no exact representable decimal result.
}
5、8种舍入行为(RoundingMode)
Enum Constant | 描述 |
---|---|
CEILING | 舍入模式向正无穷大舍入。 |
DOWN | 舍入模式向零舍入。 |
FLOOR | 舍入模式向负无穷大舍入。 |
HALF_DOWN | 舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下向下舍入。 |
HALF_EVEN | 舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下,向着偶邻居舍入。 |
HALF_UP | 舍入模式向“最近邻居”舍入,除非两个邻居等距,在这种情况下向上舍入。 |
UNNECESSARY | 舍入模式断言所请求的操作具有精确结果,因此不需要舍入。 |
UP | 舍入模式从零开始舍入。 |
static void setScale(BigDecimal bd) {
setScale(bd, 2);
}
static void setScale(BigDecimal bd, int newScale) {
System.out.println("CEILING:"+bd.setScale(newScale, RoundingMode.CEILING));
System.out.println("UP:"+bd.setScale(newScale, RoundingMode.UP));
System.out.println("HALF_UP:"+bd.setScale(newScale, RoundingMode.HALF_UP));
System.out.println("FLOOR:"+bd.setScale(newScale, RoundingMode.FLOOR));
System.out.println("DOWN:"+bd.setScale(newScale, RoundingMode.DOWN));
System.out.println("HALF_DOWN:"+bd.setScale(newScale, RoundingMode.HALF_DOWN));
System.out.println("HALF_EVEN:"+bd.setScale(newScale, RoundingMode.HALF_EVEN));
// System.out.println(bd.setScale(newScale, RoundingMode.UNNECESSARY));
}
setScale(new BigDecimal("12.345"));
CEILING:12.35
UP:12.35
HALF_UP:12.35
FLOOR:12.34
DOWN:12.34
HALF_DOWN:12.34
HALF_EVEN:12.34
setScale(new BigDecimal("67.823"));
CEILING:67.83
UP:67.83
HALF_UP:67.82
FLOOR:67.82
DOWN:67.82
HALF_DOWN:67.82
HALF_EVEN:67.82
setScale(new BigDecimal("-12.345"));
CEILING:-12.34
UP:-12.35
HALF_UP:-12.35
FLOOR:-12.35
DOWN:-12.34
HALF_DOWN:-12.34
HALF_EVEN:-12.34
setScale(new BigDecimal("-67.823"));
CEILING:-67.82
UP:-67.83
HALF_UP:-67.82
FLOOR:-67.83
DOWN:-67.82
HALF_DOWN:-67.82
HALF_EVEN:-67.82
6、常见问题
问题1:精度丢失
System.out.println(new BigDecimal(0.1)); // 错误,0.1000000000000000055511151231257827021181583404541015625
System.out.println(BigDecimal.valueOf(0.1)); // 正常,0.1
System.out.println(BigDecimal.valueOf(0.111111111111111111234)); // 错误,0.1111111111111111
解决方法
传递字符串而非浮点类型
System.out.println(new BigDecimal("0.1")); // 正常,0.1
System.out.println(new BigDecimal("0.111111111111111111234")); // 正常,0.111111111111111111234
问题2:等值比较
正常比较
System.out.println(new BigDecimal("1.0").equals(new BigDecimal("1.0"))); // true
System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1.0"))); // 0
System.out.println(new BigDecimal("1.0").equals(new BigDecimal("1.1"))); // false
System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1.1"))); // -1
异常比较
System.out.println(new BigDecimal("1.0").equals(new BigDecimal("1.00"))); // false,结果值异常
System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1.00"))); // 0,结果值正常
解决方法
比较两个BigDecimal值采用compareTo
问题3:无限精度
System.out.println(new BigDecimal(1).divide(new BigDecimal(3))); // Non-terminating decimal expansion; no exact representable decimal result
解决方法
使用舍入行为
System.out.println(new BigDecimal(1).divide(new BigDecimal(3), 2, RoundingMode.HALF_UP)); // 0.33
问题4:打印输出
BigDecimal bd = new BigDecimal("1E+10");
System.out.println(bd.toString()); // 1E+10
System.out.println(bd.toPlainString()); // 10000000000
System.out.println(bd.toEngineeringString()); // 10E+9
问题原因
- toString :必要时使用科学计数法
- toPlainString : 不使用任何指数
- toEngineeringString:必要时使用工程计数法,要求幂必须是3的倍数
问题5:计算参数为null
System.out.println(new BigDecimal("1").add(new BigDecimal("2")));// 正常:3
System.out.println(new BigDecimal((char[]) null).add(new BigDecimal("2")));// 异常:java.lang.NullPointerException
System.out.println(new BigDecimal("1").add(new BigDecimal((char[]) null)));// 异常:java.lang.NullPointerException
问题6:被除数为0
System.out.println(new BigDecimal("1").divide(new BigDecimal("0"))); // 异常:Division by zero