Java 常用类库之 BigDecimal
完整名java.math.BigDecimal
提供不可变的,任意精度的带符号十进制数。一个BigDecimal
有一个任意精度的整型非缩放值unscaledValue
和一个 32 位整型缩放值scale
组成。scale
就是用于指定unscaledValue
的缩放量级,scale >= 0
时,它表示小数点右边的位数,scale < 0
时,它表示当前BigDecimal
对象对应的数值为unscaledValue*10^(-scale)
。
BigDecimal
类提供了算术,缩放操作,舍入,比较,散列和格式转换的操作。 toString()
方法提供了一个BigDecimal
的规范表示 。 由于BigDecimal
对象是可变的,所以每次算数操作都返回一个新的BigDecimal
对象表示运算结果。
BigDecimal
提供了表示数字 0、1 和 10 的三个整数常量。
public static final BigDecimal ZERO = ZERO_THROUGH_TEN[0];
public static final BigDecimal ONE = ZERO_THROUGH_TEN[1];
public static final BigDecimal TEN = ZERO_THROUGH_TEN[10];
这里的ZERO_THROUGH_TEN
数组保存了整数 0-10 对应的所有 BigDecimal
对象。
BigDecimal
原本提供了针对舍入操作的一系列常量,如ROUND_HALF_EVEN
等,但在 Java 9 之后被弃用,使用 RoundingMode.HALF_EVEN
等枚举值表示同样的作用。
-
构造方法
BigDecimal()
BigDecimal
的构造方法根据接收的数据种类可以分为三类:字符类型的、数字类型和BigInteger
类型。- 接收字符类型的构造器包括接收字符数组
char[]
和字符串String
。
// [0] 调用构造器 [1] public BigDecimal(char[] in, int offset, int len) { this(in,offset,len,MathContext.UNLIMITED); } // [1] public BigDecimal(char[] in, int offset, int len, MathContext mc) {} // 调用构造器 [0] public BigDecimal(char[] in) { this(in, 0, in.length); } // 调用构造器 [1] public BigDecimal(char[] in, MathContext mc) { this(in, 0, in.length, mc); } // 调用构造器 [0] public BigDecimal(String val) { this(val.toCharArray(), 0, val.length()); } // 调用构造器 [1] public BigDecimal(String val, MathContext mc) { this(val.toCharArray(), 0, val.length(), mc); }
从源码中可以看出,真正起作用的构造器就是构造器 [1],其它几个构造器都是通过直接或者间接地调用它来实现的。所以这里只需要明白构造器 [1] 的参数意义就可以了。参数
in
必须是一个可以表示某个数字的字符数组(可以包含e,表示科学计数,但也需要在有意义的位置),否则程序会产生异常NumberFormatException
;offset
和len
指定观察的范围,offset
表示从in
中观察的第一个位置,len
表示需要观察的长度即字符个数;mc
是一个MathContext
对象,用于指定以怎样的精度以及舍入方式生成BigDecimal
表示的值。举一个例子:char[] num = {'1', '3', '.', '1' ,'4', '1', '5', '9', '2'}; BigDecimal val = new BigDecimal(num, 1, 6, new MathContext(4, RoundingMode.HALF_EVEN)); System.out.println(val); /* output: 3.142 */
这里表示以
num
数组的'3'
到'5'
部分生成BigDecimal
对象,MathContext
对象指定的精度为 4(表示保留 4 个有效数字),使用RoundingMode.HALF_EVEN
的舍入方式。- 接收数字类型的构造器包括接收
double/int/long
三种基本数据类型。
public BigDecimal(double val) { this(val,MathContext.UNLIMITED); } public BigDecimal(double val, MathContext mc) {} public BigDecimal(int val) {} public BigDecimal(int val, MathContext mc) {} public BigDecimal(long val) {} public BigDecimal(long val, MathContext mc) {}
- 接收
BigInteger
对象的构造器
public BigDecimal(BigInteger val) {} public BigDecimal(BigInteger val, MathContext mc) {} public BigDecimal(BigInteger unscaledVal, int scale) {} public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {}
BigInteger
是一个与BigDecimal
类似的不可变的表示整数的对象。构造器中的参数scale
指定量级为 -scale。在看一个例子就知道了:BigInteger num = new BigInteger("12345"); BigDecimal val2 = new BigDecimal(num, 2); System.out.println(val2); /* output: 123.45 */
- 接收字符类型的构造器包括接收字符数组
-
valueOf()
该方法提供了一个直接从数据类型生成
BigDecimal
对象的方式,使用方式是直接传入需要转换的基本数据类型,支持long/double
两种基本数据类型。public static BigDecimal valueOf(long unscaledVal, int scale) {} public static BigDecimal valueOf(long val) {} public static BigDecimal valueOf(double val) {}
-
add()
public BigDecimal add(BigDecimal augend) {} // mc 用于指定结果的精度与舍入方式 public BigDecimal add(BigDecimal augend, MathContext mc) {}
使用
add()
对当前BigDecimal
对象this
跟另一个BigDecimal
对象参数augend
作加法操作,对应于数值上的this + augend
,返回结果为一个新的BigDecimal
对象。 -
subtract()
public BigDecimal subtract(BigDecimal subtrahend) {} public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {}
使用
subtract()
对当前BigDecimal
对象this
跟另一个BigDecimal
对象参数subtrahend
作减法操作,对应于数值上的this - subtrahend
,返回结果为一个新的BigDecimal
对象。 -
multiply()
public BigDecimal multiply(BigDecimal multiplicand) {} public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {}
使用
multiply()
对当前BigDecimal
对象this
跟另一个BigDecimal
对象参数multiplicand
作减法操作,对应于数值上的this * subtrahend
,返回结果为一个新的BigDecimal
对象。 -
divide()
// 可以指定结果的缩放量级 scale 和舍入方式 RoundingMode public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {} public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {} public BigDecimal divide(BigDecimal divisor) {} public BigDecimal divide(BigDecimal divisor, MathContext mc) {}
使用
divide()
对当前BigDecimal
对象this
跟另一个BigDecimal
对象参数divisor
作减法操作,对应于数值上的this / divisor
,返回结果为一个新的BigDecimal
对象。 -
divideToIntegralValue()
public BigDecimal divideToIntegralValue(BigDecimal divisor) {} public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {}
同样作除法操作,但返回所得商值的整数部分。
-
remainder()
public BigDecimal remainder(BigDecimal divisor) {} public BigDecimal remainder(BigDecimal divisor, MathContext mc) {}
使用
remainder()
对当前BigDecimal
对象this
跟另一个BigDecimal
对象参数divisor
作取余操作,对应于数值上的this % divisor
,返回结果为一个新的BigDecimal
对象。 -
divideAndRemainder()
public BigDecimal[] divideAndRemainder(BigDecimal divisor) {} public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {}
相当于同时进行了
divideToIntegralValue()
和remainder()
两个操作,返回一个BigDecimal
数组,包含两个元素,第一个是divideToIntegralValue()
的结果,第二个是remainder()
的结果。注意,如果有同时得到整数商和余数的需求,使用该方法比分别使用
divideToIntegralValue()
和remainder()
两个方法要快,因为它的内部只做了一次除法。 -
pow()
public BigDecimal pow(int n) {} public BigDecimal pow(int n, MathContext mc) {}
求幂操作,求
this
对应值的 n 次方,返回结果为一个新的BigDecimal
对象。 -
abs()
public BigDecimal abs() {} public BigDecimal abs(MathContext mc) {}
求绝对值,即求
|this|
。 -
negate()
public BigDecimal negate() {} public BigDecimal negate(MathContext mc) {}
反转操作,即求
-this
。 -
plus()
public BigDecimal plus() { return this; } public BigDecimal plus(MathContext mc) {}
返回当前
BigDecimal
的对象值,即+this
。它的存在是为了和negate()
方法保持对称性。 -
signum()
public int signum() {}
返回当前
BigDecimal
表示数值的符号。返回 -1 代表负数,0 代表零,1 代表正数。 -
scale()
public int scale() { return scale; }
返回当前
BigDecimal
对象的scale
值。scale
值的作用已经在开头说明。 -
percision()
public int precision() {}
返回当前
BigDecimal
的精度,即有效位数。 -
unscaledValue()
public BigInteger unscaledValue() {}
返回一个
BigInteger
对象(假设为unscaledValue
),其对应的值为当前BigDecimal
的非缩放值,即是this * 10^(this.scale())
。 -
round()
public BigDecimal round(MathContext mc) {}
根据参数
mc
指定的精度返回一个近似值的BigDecimal
对象。 -
setScale()
public BigDecimal setScale(int newScale, RoundingMode roundingMode) {} public BigDecimal setScale(int newScale) {}
设置缩放量级。
setScale()
主要用于对BigDecimal
数据小数点后的位数进行进位、舍位、截断等操作。 -
movePointLeft()
和movePointRight()
public BigDecimal movePointLeft(int n) {} public BigDecimal movePointRight(int n) {}
前者左移小数点,后者右移小数点,返回移动小数点后的一个新
BigDecimal
对象。 -
scaleByPowerOfTen()
public BigDecimal scaleByPowerOfTen(int n) {}
在原数上乘以 10 的 n 次方,返回新的
BigDecimal
对象。 -
stripTrailingZeros()
public BigDecimal stripTrailingZeros() {}
返回一个
BigDecimal
对象,其对应的数值等于原对象数值,但移除了尾部零。比如对于值为 600.0 的BigDecimal
,其 [BigInteger
,scale
] 组成为 [6000, 1],那么通过该方法得到的BigDecimal
其值为 6e2,对应的 [BigInteger
,scale
] 组成为 [6, -2]。如果该BigDecimal
在数值上等于零,则方法返回BigDecimal.ZERO
。 -
compareTo()
public int compareTo(BigDecimal val) {}
比较当前
BigDecimal
值和val
对象值,返回 -1、0 或 1,分别代表当前BigDecimal
值小于、等于或小于val
值。对于两个值相同而 scale 值不同的BigDecimal
对象,比如其值为 2.0 和 2.00,该方法判定为两者相等。 -
equals()
public boolean equals(Object x) {}
判断当前
BigDecimal
对象于所给参数对象x
是否相等。与compareTo()
不同,equals()
要求只有两个BigDecimal
的 value 值和 scale 值都相等时,才判定两者相等(所以 2.0 和 2.00 是不相等的)。 -
min()
和max()
public BigDecimal min(BigDecimal val) {} public BigDecimal max(BigDecimal val) {}
前者返回当前
BigDecimal
对象和val
之间的最小值,后者返回两者之间的最大值。 -
hashCode()
返回当前对象的哈希码(2.0 和 2.00 的哈希码是不同的)。
-
toString()
、toEngineeringString()
和toPlainString()
public String toString() {} public String toEngineeringString() { public String toPlainString() {}
toString()
以字符串形式返回当前BigDecimal
对象表示的数值,必要时会使用科学计数法。toEngineeringString()
基本上和toString()
返回同样的结果。不同的地方在于当返回的结果为科学计数法的形式时。toPlainString()
不会返回科学计数法的形式。看一个例子吧:BigDecimal val = new BigDecimal(new BigInteger("123456"), -9); System.out.println(val); System.out.println(val.toEngineeringString()); System.out.println(val.toPlainString()); /* output: 1.23456E+14 123.456E+12 123456000000000 */
toEngineeringString()
在输出为科学计数法时,会让 10 的指数为 3 的倍数,这样表示出的整数部分就处于 1 到 999 之间。 -
toBigInteger()
和toBigIntegerExact()
public BigInteger toBigInteger() {} public BigInteger toBigIntegerExact() {}
两者都是将当前的
BigDecimal
转换得到一个BigInteger
对象。前者在转换中会丢掉原数的小鼠部分,所以可能有信息损失;后者不允许信息损失,所以当原数存在非零小数部分时,会直接抛出异常ArithmeticException
。 -
lnogValue()
和longValueExact()
public long longValue(){} public long longValueExact() {}
两者都时将当前
BigDecimal
转换得到一个long
型整数。前者类似于基本收缩转换(arrowing primitive conversion),即去掉小数部分,并且当整数部分的BIgInteger
值超出long
型数据范围时,取其低 64 位,因此可能有信息损失;后者不允许信息损失,所以当遇到非零小数部分或者整数部分超限时,直接抛出异常ArithmeticException
。 -
shorValueExact()
和byteValueExact()
public short shortValueExact() {} public byte byteValueExact() {}
作用和
longValueExact()
类似,只是分别转换得到short
型和1byte
型数据。都不允许信息丢失。 -
floatValue()
和doubleValue()
public float floatValue(){} public double doubleValue(){}
转换当前
BigDecimal
对象值得到浮点型数据,转换允许信息损失。 -
ulp()
public BigDecimal ulp() {}
返回当前
BigDecimal
的最后位置单位大小(ulp)。实际上它的值为 [1
,this.scale()
],即1*10^(-this.scale())
。
以下是从 Java 9 开始加入的方法:
-
sqrt()
public BigDecimal sqrt(MathContext mc) {}
开平方操作,返回结果为一个新的
BigDecimal
对象。