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

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");
        }
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章