天天看点

Java 常用类库之 BigDecimal

完整名<code>java.math.BigDecimal</code>

提供不可变的,任意精度的带符号十进制数。一个<code>BigDecimal</code>有一个任意精度的整型非缩放值<code>unscaledValue</code>和一个 32 位整型缩放值<code>scale</code>组成。<code>scale</code>就是用于指定<code>unscaledValue</code>的缩放量级,<code>scale &gt;= 0</code>时,它表示小数点右边的位数,<code>scale &lt; 0</code>时,它表示当前<code>BigDecimal</code>对象对应的数值为<code>unscaledValue*10^(-scale)</code>。

<code>BigDecimal</code>类提供了算术,缩放操作,舍入,比较,散列和格式转换的操作。 <code>toString()</code>方法提供了一个<code>BigDecimal</code>的规范表示 。 由于<code>BigDecimal</code>对象是可变的,所以每次算数操作都返回一个新的<code>BigDecimal</code>对象表示运算结果。

<code>BigDecimal</code>提供了表示数字 0、1 和 10 的三个整数常量。

这里的<code>ZERO_THROUGH_TEN</code>数组保存了整数 0-10 对应的所有 <code>BigDecimal</code>对象。

<code>BigDecimal</code>原本提供了针对舍入操作的一系列常量,如<code>ROUND_HALF_EVEN</code>等,但在 Java 9 之后被弃用,使用 <code>RoundingMode.HALF_EVEN</code>等枚举值表示同样的作用。

构造方法<code>BigDecimal()</code>

<code>BigDecimal</code>的构造方法根据接收的数据种类可以分为三类:字符类型的、数字类型和<code>BigInteger</code>类型。

接收字符类型的构造器包括接收字符数组<code>char[]</code>和字符串<code>String</code>。

从源码中可以看出,真正起作用的构造器就是构造器 [1],其它几个构造器都是通过直接或者间接地调用它来实现的。所以这里只需要明白构造器 [1] 的参数意义就可以了。参数<code>in</code>必须是一个可以表示某个数字的字符数组(可以包含e,表示科学计数,但也需要在有意义的位置),否则程序会产生异常<code>NumberFormatException</code>;<code>offset</code>和<code>len</code>指定观察的范围,<code>offset</code>表示从<code>in</code>中观察的第一个位置,<code>len</code>表示需要观察的长度即字符个数;<code>mc</code>是一个<code>MathContext</code>对象,用于指定以怎样的精度以及舍入方式生成<code>BigDecimal</code>表示的值。举一个例子:

这里表示以<code>num</code>数组的 <code>'3'</code>到<code>'5'</code>部分生成<code>BigDecimal</code>对象,<code>MathContext</code>对象指定的精度为 4(表示保留 4 个有效数字),使用<code>RoundingMode.HALF_EVEN</code>的舍入方式。

接收数字类型的构造器包括接收<code>double/int/long</code>三种基本数据类型。

接收<code>BigInteger</code>对象的构造器

<code>BigInteger</code>是一个与<code>BigDecimal</code>类似的不可变的表示整数的对象。构造器中的参数<code>scale</code>指定量级为 -scale。在看一个例子就知道了:

<code>valueOf()</code>

该方法提供了一个直接从数据类型生成<code>BigDecimal</code>对象的方式,使用方式是直接传入需要转换的基本数据类型,支持<code>long/double</code>两种基本数据类型。

<code>add()</code>

使用<code>add()</code>对当前<code>BigDecimal</code>对象<code>this</code>跟另一个<code>BigDecimal</code>对象参数<code>augend</code>作加法操作,对应于数值上的<code>this + augend</code>,返回结果为一个新的<code>BigDecimal</code>对象。

<code>subtract()</code>

使用<code>subtract()</code>对当前<code>BigDecimal</code>对象<code>this</code>跟另一个<code>BigDecimal</code>对象参数<code>subtrahend</code>作减法操作,对应于数值上的<code>this - subtrahend</code>,返回结果为一个新的<code>BigDecimal</code>对象。

<code>multiply()</code>

使用<code>multiply()</code>对当前<code>BigDecimal</code>对象<code>this</code>跟另一个<code>BigDecimal</code>对象参数<code>multiplicand</code>作减法操作,对应于数值上的<code>this * subtrahend</code>,返回结果为一个新的<code>BigDecimal</code>对象。

<code>divide()</code>

使用<code>divide()</code>对当前<code>BigDecimal</code>对象<code>this</code>跟另一个<code>BigDecimal</code>对象参数<code>divisor</code>作减法操作,对应于数值上的<code>this / divisor</code>,返回结果为一个新的<code>BigDecimal</code>对象。

<code>divideToIntegralValue()</code>

同样作除法操作,但返回所得商值的整数部分。

<code>remainder()</code>

使用<code>remainder()</code>对当前<code>BigDecimal</code>对象<code>this</code>跟另一个<code>BigDecimal</code>对象参数<code>divisor</code>作取余操作,对应于数值上的<code>this % divisor</code>,返回结果为一个新的<code>BigDecimal</code>对象。

<code>divideAndRemainder()</code>

相当于同时进行了<code>divideToIntegralValue()</code>和<code>remainder()</code>两个操作,返回一个<code>BigDecimal</code>数组,包含两个元素,第一个是<code>divideToIntegralValue()</code>的结果,第二个是<code>remainder()</code>的结果。

注意,如果有同时得到整数商和余数的需求,使用该方法比分别使用<code>divideToIntegralValue()</code>和<code>remainder()</code>两个方法要快,因为它的内部只做了一次除法。

<code>pow()</code>

求幂操作,求<code>this</code>对应值的 n 次方,返回结果为一个新的<code>BigDecimal</code>对象。

<code>abs()</code>

求绝对值,即求<code>|this|</code>。

<code>negate()</code>

反转操作,即求<code>-this</code>。

<code>plus()</code>

返回当前<code>BigDecimal</code>的对象值,即<code>+this</code>。它的存在是为了和<code>negate()</code>方法保持对称性。

<code>signum()</code>

返回当前<code>BigDecimal</code>表示数值的符号。返回 -1 代表负数,0 代表零,1 代表正数。

<code>scale()</code>

返回当前<code>BigDecimal</code>对象的<code>scale</code>值。<code>scale</code>值的作用已经在开头说明。

<code>percision()</code>

返回当前<code>BigDecimal</code>的精度,即有效位数。

<code>unscaledValue()</code>

返回一个<code>BigInteger</code>对象(假设为<code>unscaledValue</code>),其对应的值为当前<code>BigDecimal</code>的非缩放值,即是<code>this * 10^(this.scale())</code>。

<code>round()</code>

根据参数<code>mc</code>指定的精度返回一个近似值的<code>BigDecimal</code>对象。

<code>setScale()</code>

设置缩放量级。<code>setScale()</code>主要用于对<code>BigDecimal</code>数据小数点后的位数进行进位、舍位、截断等操作。

<code>movePointLeft()</code>和<code>movePointRight()</code>

前者左移小数点,后者右移小数点,返回移动小数点后的一个新<code>BigDecimal</code>对象。

<code>scaleByPowerOfTen()</code>

在原数上乘以 10 的 n 次方,返回新的<code>BigDecimal</code>对象。

<code>stripTrailingZeros()</code>

返回一个<code>BigDecimal</code>对象,其对应的数值等于原对象数值,但移除了尾部零。比如对于值为 600.0 的<code>BigDecimal</code>,其 [<code>BigInteger</code>, <code>scale</code>] 组成为 [6000, 1],那么通过该方法得到的<code>BigDecimal</code>其值为 6e2,对应的 [<code>BigInteger</code>, <code>scale</code>] 组成为 [6, -2]。如果该<code>BigDecimal</code>在数值上等于零,则方法返回<code>BigDecimal.ZERO</code> 。

<code>compareTo()</code>

比较当前<code>BigDecimal</code>值和<code>val</code>对象值,返回 -1、0 或 1,分别代表当前<code>BigDecimal</code>值小于、等于或小于<code>val</code>值。对于两个值相同而 scale 值不同的<code>BigDecimal</code>对象,比如其值为 2.0 和 2.00,该方法判定为两者相等。

<code>equals()</code>

判断当前<code>BigDecimal</code>对象于所给参数对象<code>x</code>是否相等。与<code>compareTo()</code>不同,<code>equals()</code>要求只有两个<code>BigDecimal</code>的 value 值和 scale 值都相等时,才判定两者相等(所以 2.0 和 2.00 是不相等的)。

<code>min()</code>和<code>max()</code>

前者返回当前<code>BigDecimal</code>对象和<code>val</code>之间的最小值,后者返回两者之间的最大值。

<code>hashCode()</code>

返回当前对象的哈希码(2.0 和 2.00 的哈希码是不同的)。

<code>toString()</code>、<code>toEngineeringString()</code>和<code>toPlainString()</code>

<code>toString()</code>以字符串形式返回当前<code>BigDecimal</code>对象表示的数值,必要时会使用科学计数法。

<code>toEngineeringString()</code>基本上和<code>toString()</code>返回同样的结果。不同的地方在于当返回的结果为科学计数法的形式时。

<code>toPlainString()</code>不会返回科学计数法的形式。看一个例子吧:

<code>toEngineeringString()</code>在输出为科学计数法时,会让 10 的指数为 3 的倍数,这样表示出的整数部分就处于 1 到 999 之间。

<code>toBigInteger()</code>和<code>toBigIntegerExact()</code>

两者都是将当前的<code>BigDecimal</code>转换得到一个<code>BigInteger</code>对象。前者在转换中会丢掉原数的小鼠部分,所以可能有信息损失;后者不允许信息损失,所以当原数存在非零小数部分时,会直接抛出异常<code>ArithmeticException</code>。

<code>lnogValue()</code>和<code>longValueExact()</code>

两者都时将当前<code>BigDecimal</code>转换得到一个<code>long</code>型整数。前者类似于基本收缩转换(arrowing primitive conversion),即去掉小数部分,并且当整数部分的<code>BIgInteger</code>值超出<code>long</code>型数据范围时,取其低 64 位,因此可能有信息损失;后者不允许信息损失,所以当遇到非零小数部分或者整数部分超限时,直接抛出异常<code>ArithmeticException</code>。

<code>shorValueExact()</code>和<code>byteValueExact()</code>

作用和<code>longValueExact()</code>类似,只是分别转换得到<code>short</code>型和1<code>byte</code>型数据。都不允许信息丢失。

<code>floatValue()</code>和<code>doubleValue()</code>

转换当前<code>BigDecimal</code>对象值得到浮点型数据,转换允许信息损失。

<code>ulp()</code>

返回当前<code>BigDecimal</code>的最后位置单位大小(ulp)。实际上它的值为 [<code>1</code>, <code>this.scale()</code>],即 <code>1*10^(-this.scale())</code>。

以下是从 Java 9 开始加入的方法:

<code>sqrt()</code>

开平方操作,返回结果为一个新的<code>BigDecimal</code>对象。