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