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等枚举值表示同样的作用。

  1. 构造方法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,表示科学计数,但也需要在有意义的位置),否则程序会产生异常NumberFormatExceptionoffsetlen指定观察的范围,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
    */
    
  2. valueOf()

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

    public static BigDecimal valueOf(long unscaledVal, int scale) {}
    public static BigDecimal valueOf(long val) {}
    public static BigDecimal valueOf(double val) {}
    
  3. add()

    public BigDecimal add(BigDecimal augend) {}
    // mc 用于指定结果的精度与舍入方式
    public BigDecimal add(BigDecimal augend, MathContext mc) {}
    

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

  4. subtract()

    public BigDecimal subtract(BigDecimal subtrahend) {}
    public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {}
    

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

  5. multiply()

    public BigDecimal multiply(BigDecimal multiplicand) {}
    public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {}
    

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

  6. 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对象。

  7. divideToIntegralValue()

    public BigDecimal divideToIntegralValue(BigDecimal divisor) {}
    public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {}
    

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

  8. remainder()

    public BigDecimal remainder(BigDecimal divisor) {}
    public BigDecimal remainder(BigDecimal divisor, MathContext mc) {}
    

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

  9. divideAndRemainder()

    public BigDecimal[] divideAndRemainder(BigDecimal divisor) {}
    public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {}
    

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

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

  10. pow()

    public BigDecimal pow(int n) {}
    public BigDecimal pow(int n, MathContext mc) {}
    

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

  11. abs()

    public BigDecimal abs() {}
    public BigDecimal abs(MathContext mc) {}
    

    求绝对值,即求|this|

  12. negate()

    public BigDecimal negate() {}
    public BigDecimal negate(MathContext mc) {}
    

    反转操作,即求-this

  13. plus()

    public BigDecimal plus() { return this; }
    public BigDecimal plus(MathContext mc) {}
    

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

  14. signum()

    public int signum() {}
    

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

  15. scale()

    public int scale() {
        return scale;
    }
    

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

  16. percision()

    public int precision() {}
    

    返回当前BigDecimal的精度,即有效位数。

  17. unscaledValue()

    public BigInteger unscaledValue() {}
    

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

  18. round()

    public BigDecimal round(MathContext mc) {}
    

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

  19. setScale()

    public BigDecimal setScale(int newScale, RoundingMode roundingMode) {}
    public BigDecimal setScale(int newScale) {}
    

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

  20. movePointLeft()movePointRight()

    public BigDecimal movePointLeft(int n) {}
    public BigDecimal movePointRight(int n) {}
    

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

  21. scaleByPowerOfTen()

    public BigDecimal scaleByPowerOfTen(int n) {}
    

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

  22. stripTrailingZeros()

    public BigDecimal stripTrailingZeros() {}
    

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

  23. compareTo()

    public int compareTo(BigDecimal val) {}
    

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

  24. equals()

    public boolean equals(Object x) {}
    

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

  25. min()max()

    public BigDecimal min(BigDecimal val) {}
    public BigDecimal max(BigDecimal val) {}
    

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

  26. hashCode()

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

  27. 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 之间。

  28. toBigInteger()toBigIntegerExact()

    public BigInteger toBigInteger() {}
    public BigInteger toBigIntegerExact() {}
    

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

  29. lnogValue()longValueExact()

    public long longValue(){}
    public long longValueExact() {}
    

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

  30. shorValueExact()byteValueExact()

    public short shortValueExact() {}
    public byte byteValueExact() {}
    

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

  31. floatValue()doubleValue()

    public float floatValue(){}
    public double doubleValue(){}
    

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

  32. ulp()

    public BigDecimal ulp() {}
    

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

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

  1. sqrt()

    public BigDecimal sqrt(MathContext mc) {}
    

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

posted @ 2021-08-25 23:54  alterwl  阅读(238)  评论(0编辑  收藏  举报