新手注意:Java中使用BigDecimal类时要避免的坑

1、两数相除无限循环小数问题

直接看例子01:

@Test
public void BigNumber_Test () {
    BigDecimal bd = new BigDecimal("10");
    BigDecimal divNum = new BigDecimal("3");
    // 除法遇到除不尽时,这种写法会抛出异常ArithmeticException
    BigDecimal bigDecimal = bd.divide(divNum); // NG java.lang.ArithmeticException
    System.out.println(bd.divide(divNum, 2)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_UP)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_DOWN)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_CEILING)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_FLOOR)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_HALF_UP)); // OK
    System.out.println(bd.divide(divNum, 2, BigDecimal.ROUND_HALF_EVEN)); // OK
    System.out.println(bd.divide(new BigDecimal("4"), 2, BigDecimal.ROUND_UNNECESSARY)); // OK
}

除了NG行,其他行的输出结果依次为:

4 3.34 3.33 3.34 3.33 3.33 3.33 2.50

总结:果两数相除,除不尽时,需要指定保留精度和进位方式,否则会抛出异常。

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

2、对象比较时含精度比较问题

直接看例子02:

@Test
public void BigNumber_Test () {
    BigDecimal bd = new BigDecimal("3");
    BigDecimal divNum = new BigDecimal("3.00");

    System.out.println(bd.equals(divNum)); // 输出 false
    System.out.println(bd.compareTo(divNum)); // 输出 0

    BigDecimal divNum2 = new BigDecimal("3.00");
    System.out.println(divNum.equals(divNum2)); // 输出 true
    System.out.println(divNum.compareTo(divNum2)); // 输出 0
}

总结:若要严格含精度对比是否相等需要用equals方法,若只是比较数值的大小忽略精度用compareTo方法。

3、创建对象时精度丢失问题

直接看例子03:

@Test
public void BigNumber_Test () {
    BigDecimal bd = new BigDecimal(1.15666); // 入参是double
    BigDecimal divNum = new BigDecimal("1.15666"); // 入参是String

    System.out.println(bd); // 输出:1.156660000000000021458390619955025613307952880859375
    System.out.println(divNum); // 输出:1.15666
}

总结:如果要严格保留精度,应该避免使用浮点类型做入参进行构造,尽量使用字符串格式进行构造。


举报
评论 0