Non-terminating decimal expansion; no exact representable decimal result异常

范兴文
2023-12-01

Non-terminating decimal expansion; no exact representable decimal result

翻译:无法终止小数点扩展; 没有确切的可表示的小数结果

出现的情形:

BigDecimal num1 = new BigDecimal("10");

BigDecimal num2 = new BigDecimal("3");

BigDecimal num3 = num1.divide(num2);

出现了无线循环小数。

可以使用devide重载方法BigDecimal.divide(BigDecimal divisor, int scale, RoundingMode roundingMode) ;

RoundingMode源码解析:

public enum RoundingMode {

    /**
     * Rounding mode to round away from zero.  Always increments the
     * digit prior to a non-zero discarded fraction.  Note that this
     * rounding mode never decreases the magnitude of the calculated
     * value.
     *
     * 远离0的舍入模式。总是在非零的小数前增加数值。请注意,该舍入模式不会减小计算值的大小。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code UP} rounding
     *<tr align=right><td>5.5</td>  <td>6</td>
     *<tr align=right><td>2.5</td>  <td>3</td>
     *<tr align=right><td>1.6</td>  <td>2</td>
     *<tr align=right><td>1.1</td>  <td>2</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-2</td>
     *<tr align=right><td>-1.6</td> <td>-2</td>
     *<tr align=right><td>-2.5</td> <td>-3</td>
     *<tr align=right><td>-5.5</td> <td>-6</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:6     3   2    2    1    -1    -2    -2    -3    -6
     */
    UP(BigDecimal.ROUND_UP),

    /**
     * Rounding mode to round towards zero.  Never increments the digit
     * prior to a discarded fraction (i.e., truncates).  Note that this
     * rounding mode never increases the magnitude of the calculated value.
     *
     * 靠近0的舍入模式。在放弃的小数之前不递增数值(即截断)。请注意,舍入模式不会增加计算值的大小。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code DOWN} rounding
     *<tr align=right><td>5.5</td>  <td>5</td>
     *<tr align=right><td>2.5</td>  <td>2</td>
     *<tr align=right><td>1.6</td>  <td>1</td>
     *<tr align=right><td>1.1</td>  <td>1</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-1</td>
     *<tr align=right><td>-1.6</td> <td>-1</td>
     *<tr align=right><td>-2.5</td> <td>-2</td>
     *<tr align=right><td>-5.5</td> <td>-5</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:5     2   1    1    1    -1    -1    -1    -2    -5
     */
    DOWN(BigDecimal.ROUND_DOWN),

    /**
     * Rounding mode to round towards positive infinity.  If the
     * result is positive, behaves as for {@code RoundingMode.UP};
     * if negative, behaves as for {@code RoundingMode.DOWN}.  Note
     * that this rounding mode never decreases the calculated value.
     *
     * 向正无穷大舍入。如果结果是正数,执行RoundingMode.UP;如果结果是负数,执行RoundingMode.DOWN。
     * 请注意,这个舍入模式决不会减少计算值。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code CEILING} rounding
     *<tr align=right><td>5.5</td>  <td>6</td>
     *<tr align=right><td>2.5</td>  <td>3</td>
     *<tr align=right><td>1.6</td>  <td>2</td>
     *<tr align=right><td>1.1</td>  <td>2</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-1</td>
     *<tr align=right><td>-1.6</td> <td>-1</td>
     *<tr align=right><td>-2.5</td> <td>-2</td>
     *<tr align=right><td>-5.5</td> <td>-5</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:6     3   2    2    1    -1    -1    -1    -2    -5
     */
    CEILING(BigDecimal.ROUND_CEILING),

    /**
     * Rounding mode to round towards negative infinity.  If the
     * result is positive, behave as for {@code RoundingMode.DOWN};
     * if negative, behave as for {@code RoundingMode.UP}.  Note that
     * this rounding mode never increases the calculated value.
     *
     * 向负无穷大舍入。如果结果是正数,执行RoundingMode.DOWN;如果结果是负数,执行RoundingMode.UP。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code FLOOR} rounding
     *<tr align=right><td>5.5</td>  <td>5</td>
     *<tr align=right><td>2.5</td>  <td>2</td>
     *<tr align=right><td>1.6</td>  <td>1</td>
     *<tr align=right><td>1.1</td>  <td>1</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-2</td>
     *<tr align=right><td>-1.6</td> <td>-2</td>
     *<tr align=right><td>-2.5</td> <td>-3</td>
     *<tr align=right><td>-5.5</td> <td>-6</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:5     2   1    1    1    -1    -2    -2    -3    -6
     */
    FLOOR(BigDecimal.ROUND_FLOOR),

    /**
     * Rounding mode to round towards {@literal "nearest neighbor"}
     * unless both neighbors are equidistant, in which case round up.
     * Behaves as for {@code RoundingMode.UP} if the discarded
     * fraction is ≥ 0.5; otherwise, behaves as for
     * {@code RoundingMode.DOWN}.  Note that this is the rounding
     * mode commonly taught at school.
     *
     * 向最邻近的地方舍入。除非离左右两边的的数值是等距的,那么就是用ROUND_UP模式。
     * 如果舍弃的小数部分大于等于0.5,执行RoundingMode.UP,否则执行RoundingMode.DOWN。
     * 请注意,这是学校常用的四舍五入舍入模式。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code HALF_UP} rounding
     *<tr align=right><td>5.5</td>  <td>6</td>
     *<tr align=right><td>2.5</td>  <td>3</td>
     *<tr align=right><td>1.6</td>  <td>2</td>
     *<tr align=right><td>1.1</td>  <td>1</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-1</td>
     *<tr align=right><td>-1.6</td> <td>-2</td>
     *<tr align=right><td>-2.5</td> <td>-3</td>
     *<tr align=right><td>-5.5</td> <td>-6</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:6     3   2    1    1    -1    -1    -2    -3    -6
     */
    HALF_UP(BigDecimal.ROUND_HALF_UP),

    /**
     * Rounding mode to round towards {@literal "nearest neighbor"}
     * unless both neighbors are equidistant, in which case round
     * down.  Behaves as for {@code RoundingMode.UP} if the discarded
     * fraction is > 0.5; otherwise, behaves as for
     * {@code RoundingMode.DOWN}.
     *
     * 向最邻近的地方舍入。除非离左右两边的的数值是等距的,那么就是用ROUND_DOWN模式。
     * 如果舍弃的小数部分大于0.5,执行RoundingMode.UP,否则执行RoundingMode.DOWN。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code HALF_DOWN} rounding
     *<tr align=right><td>5.5</td>  <td>5</td>
     *<tr align=right><td>2.5</td>  <td>2</td>
     *<tr align=right><td>1.6</td>  <td>2</td>
     *<tr align=right><td>1.1</td>  <td>1</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-1</td>
     *<tr align=right><td>-1.6</td> <td>-2</td>
     *<tr align=right><td>-2.5</td> <td>-2</td>
     *<tr align=right><td>-5.5</td> <td>-5</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:5     2   2    1    1    -1    -1    -2    -2    -5
     */
    HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),

    /**
     * Rounding mode to round towards the {@literal "nearest neighbor"}
     * unless both neighbors are equidistant, in which case, round
     * towards the even neighbor.  Behaves as for
     * {@code RoundingMode.HALF_UP} if the digit to the left of the
     * discarded fraction is odd; behaves as for
     * {@code RoundingMode.HALF_DOWN} if it's even.  Note that this
     * is the rounding mode that statistically minimizes cumulative
     * error when applied repeatedly over a sequence of calculations.
     * It is sometimes known as {@literal "Banker's rounding,"} and is
     * chiefly used in the USA.  This rounding mode is analogous to
     * the rounding policy used for {@code float} and {@code double}
     * arithmetic in Java.
     *
     * 向最邻近的地方舍入。除非离左右两边的的数值是等距的,那么就向最邻近的偶数舍入。
     * 如果舍弃部分左边的数字是奇数,执行RoundingMode.HALF_UP。如果是偶数,执行RoundingMode.HALF_DOWN。
     * 请注意,这是一个舍入模式,当在一系列计算中重复应用时,可以统计学上最小化累积误差。
     * 它有时被称为"银行家四舍五入",主要用于美国。
     * 这种舍入模式类似于Java中用于float和double算术的舍入策略。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code HALF_EVEN} rounding
     *<tr align=right><td>5.5</td>  <td>6</td>
     *<tr align=right><td>2.5</td>  <td>2</td>
     *<tr align=right><td>1.6</td>  <td>2</td>
     *<tr align=right><td>1.1</td>  <td>1</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>-1</td>
     *<tr align=right><td>-1.6</td> <td>-2</td>
     *<tr align=right><td>-2.5</td> <td>-2</td>
     *<tr align=right><td>-5.5</td> <td>-6</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5  2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:6     2   2    1    1    -1    -1    -2    -2    -6
     */
    HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),

    /**
     * Rounding mode to assert that the requested operation has an exact
     * result, hence no rounding is necessary.  If this rounding mode is
     * specified on an operation that yields an inexact result, an
     * {@code ArithmeticException} is thrown.
     *
     * 舍入模式来断言所请求的操作具有确切的结果,因此不需要舍入。
     * 如果在产生不精确结果的操作上指定了舍入模式,则抛出ArithmeticException。
     *
     *<p>Example:
     *<table border>
     *<tr valign=top><th>Input Number</th>
     *    <th>Input rounded to one digit<br> with {@code UNNECESSARY} rounding
     *<tr align=right><td>5.5</td>  <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>2.5</td>  <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>1.6</td>  <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>1.1</td>  <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>1.0</td>  <td>1</td>
     *<tr align=right><td>-1.0</td> <td>-1</td>
     *<tr align=right><td>-1.1</td> <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>-1.6</td> <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>-2.5</td> <td>throw {@code ArithmeticException}</td>
     *<tr align=right><td>-5.5</td> <td>throw {@code ArithmeticException}</td>
     *</table>
     *
     * 举个栗子:
     * 输入一个数字:5.5   2.5  1.6  1.1  1.0  -1.0  -1.1  -1.6  -2.5  -5.5
     * 舍入后的数字:异常  异常  异常  异常  1    -1   异常   异常   异常  异常
     */
    UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);

    // Corresponding BigDecimal rounding constant
    final int oldMode;

    /**
     * Constructor
     *
     * @param oldMode The {@code BigDecimal} constant corresponding to
     *        this mode
     */
    private RoundingMode(int oldMode) {
        this.oldMode = oldMode;
    }

    /**
     * Returns the {@code RoundingMode} object corresponding to a
     * legacy integer rounding mode constant in {@link BigDecimal}.
     *
     * 返回BigDecimal中对应于传统整数舍入模式常量的RoundingMode对象。
     *
     * @param  rm legacy integer rounding mode to convert
     * @return {@code RoundingMode} corresponding to the given integer.
     * @throws IllegalArgumentException integer is out of range
     */
    public static RoundingMode valueOf(int rm) {
        switch(rm) {

            case BigDecimal.ROUND_UP:
                return UP;

            case BigDecimal.ROUND_DOWN:
                return DOWN;

            case BigDecimal.ROUND_CEILING:
                return CEILING;

            case BigDecimal.ROUND_FLOOR:
                return FLOOR;

            case BigDecimal.ROUND_HALF_UP:
                return HALF_UP;

            case BigDecimal.ROUND_HALF_DOWN:
                return HALF_DOWN;

            case BigDecimal.ROUND_HALF_EVEN:
                return HALF_EVEN;

            case BigDecimal.ROUND_UNNECESSARY:
                return UNNECESSARY;

            default:
                throw new IllegalArgumentException("argument out of range");
        }
    }
}



 类似资料: