Java學習(24) -- 源碼閱讀(BigDecimal)

一、java 中使用什麼操作金額?float,double?

因爲float和double都是浮點數, 都有取值範圍, 都有精度範圍. 浮點數與通常使用的小數不同, 使用中, 往往難以確定. 常見的問題是定 義了一個浮點數, 經過一系列的計算, 它本來應該等於某個確定值, 但實際上並不是! 金額必須是完全精確的計算, 故不能使用double或者float, 而應該採用java.math.BigDecimal.

二、 BigDecimal 的加減乘除

Java中å­å¨éé¢ç¨ä»ä¹æ°æ®ç±»åï¼

三、  BigDecimal 比較大小

public int compareTo(BigDecimal val) {
        // Quick path for equal scale and non-inflated case.
        if (scale == val.scale) {
            long xs = intCompact;
            long ys = val.intCompact;
            if (xs != INFLATED && ys != INFLATED)
                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
        }
        int xsign = this.signum();
        int ysign = val.signum();
        if (xsign != ysign)
            return (xsign > ysign) ? 1 : -1;
        if (xsign == 0)
            return 0;
        int cmp = compareMagnitude(val);
        return (xsign > 0) ? cmp : -cmp;
    }

由上可知: A.compareTo(B)

     1) 返回爲 -1 時 A < B

     2) 返回爲  1 時 A > B

     3) 返回爲  0 時 A = B

四、小數位數及四捨五入規則

 Java中å­å¨éé¢ç¨ä»ä¹æ°æ®ç±»åï¼

五、mysql數據庫設計

 BigDecimal在進行入庫時, 數據庫選擇decimal類型, 長度可以自定義, 如18; 小數點我們項目中用的是2, 保留2位小數. 此外還要注意的就是默認值, 一定寫成0.00, 不要用默認的NULL, 否則在進行加減排序等操作時, 會帶來轉換的麻煩!

    `balance` decimal(18,2) DEFAULT '0.00' COMMENT '賬戶餘額',

 

六、源碼

/**
 * 不可變的、任意精度的有符號十進制數。BigDecimal 由任意精度的整數非標度值 和 32 位的整數標度 (scale) 組成。
 * 如果爲零或正數,則標度是小數點後的位數。如果爲負數,則將該數的非標度值乘以 10 的負 scale 次冪。
 * 因此,BigDecimal 表示的數值是 (unscaledValue × 10的-scale次冪)。 
 * BigDecimal 類提供以下操作:算術、標度操作、舍入、比較、哈希算法和格式轉換。
 * toString() 方法提供 BigDecimal 的規範表示形式。 
 * BigDecimal 類使用戶能完全控制舍入行爲。如果未指定舍入模式,並且無法表示準確結果,則拋出一個異常;
 * 否則,通過向該操作提供適當的 MathContext 對象,可以對已選擇的精度和舍入模式執行計算。
 * 在任何情況下,可以爲舍入控制提供八種舍入模式。使用此類(例如,ROUND_HALF_UP)中的整數字段來表示舍入模式已過時;
 * 應改爲使用 RoundingMode enum(例如,RoundingMode.HALF_UP)的枚舉值。 
 * 當爲 MathContext 對象提供 0 的精度設置(例如,MathContext.UNLIMITED)時,算術運算是準確的,
 * 它們是不採用任何 MathContext 對象的算術方法。(這是第 5 版之前的版本支持的唯一行爲。)爲了計算準確結果,
 * 不使用附帶 0 精度設置的 MathContext 對象的舍入模式設置,因此與該對象無關。在除法中,準確的商可能是一個無限長的十進制擴展;
 * 例如,1 除以 3 所得的商。如果商具有無窮的十進制擴展,但是指定了該操作返回準確結果,則拋出 ArithmeticException。
 * 否則,像其他操作那樣,返回除法運算的準確結果。 
 * 當精度設置不爲 0 時,BigDecimal 算法的規則完全符合 ANSI X3.274-1996 和 ANSI X3.274-1996/AM 1-2000( 7.4 節)中定義的算法的可選操作模式。
 * 與上述標準不同,BigDecimal 包括多種舍入模式,它們對於版本 5 以前的 BigDecimal 版本中的除法是強制性的。
 * 這些 ANSI 標準和 BigDecimal 規範之間的任何衝突都按照有利於 BigDecimal 的方式進行解決。 
 * 由於同一數值可以有不同的表示形式(具有不同的標度),因此運算和舍入的規則必須同時指定數值結果和結果表示形式中所用的標度。 
 * 一般情況下,當準確結果(在除法中,可能有無限多位)比返回的數值具有更多位數時,舍入模式和精度設置確定操作如何返回具有有限位數的結果。
 *  首先,MathContext 的 precision 設置指定要返回的總位數;這確定了結果的精度。
 *  位數計數從準確結果的最左邊的非零數字開始。舍入模式確定丟棄的尾部位數如何影響返回的結果。 
 *  對於所有算術運算符,運算的執行方式是,首先計算準確的中間結果,然後,使用選擇的舍入模式將其舍入爲精度設置(如有必要)指定的位數。
 *  如果不返回準確結果,則將丟棄準確結果的某些數位。當舍入增加了返回結果的大小時,前導數字“9”的進位傳播可能會創建新的數位。
 *  例如,將值 999.9 舍入爲三位數字,則在數值上等於一千,表示爲 100×101。在這種情況下,新的 "1" 是返回結果的前導數位。 
 *  除了邏輯的準確結果外,每種算術運算都有一個表示結果的首選標度。下表列出了每個運算的首選標度。 算術運算結果的首選標度  運算 結果的首選標度 
 *  	加 max(addend.scale(), augend.scale()) 
 *  	減 max(minuend.scale(), subtrahend.scale()) 
 *  	乘 multiplier.scale() + multiplicand.scale() 
 *  	除 dividend.scale() - divisor.scale() 
 *  這些標度是返回準確算術結果的方法使用的標度;準確相除可能必須使用較大的標度除外,因爲準確的結果可能有較多的位數。例如,1/32 得到 0.03125。 
 *  舍入之前,邏輯的準確中間結果的標度是該運算的首選標度。如果用 precision 位數無法表示準確的數值結果,則舍入會選擇要返回的一組數字,
 *  並將該結果的標度從中間結果的標度減小到可以表示實際返回的 precision 位數的最小標度。
 *  如果準確結果可以使用最多 precision 個數字表示,則返回具有最接近首選標度的標度的結果表示形式。
 *  尤其是,通過移除結尾零並減少標度,可以用少於 precision 個數字來表示準確的可表示的商。例如,使用 floor 舍入模式將結果舍入爲三個數字,
 *  	19/100 = 0.19 // integer=19, scale=2 
 *  但是
 *  	21/110 = 0.190 // integer=190, scale=3 
 *  注意,對於加、減和乘,標度的縮減量將等於丟棄的準確結果的數字位置數。如果舍入導致進位傳播創建一個新的高位,則當未創建新的數位時,會丟棄該結果的附加數字。 
 *  其他方法可能與舍入語義稍微不同。例如,使用指定的算法的 pow 方法得到的結果可能偶爾不同於舍入得到的算術結果,如最後一位有多個單位(ulp)。 
 *  可以通過兩種類型的操作來處理 BigDecimal 的標度:標度/舍入操作和小數點移動操作。標度/舍入操作(setScale 和 round)返回 BigDecimal,
 *  其值近似地(或精確地)等於操作數的值,但是其標度或精度是指定的值;即:它們會增加或減少對其值具有最小影響的存儲數的精度。
 *  小數點移動操作(movePointLeft 和 movePointRight)返回從操作數創建的 BigDecimal,創建的方法是按指定方向將小數點移動一個指定距離。 
 *  爲了簡潔明瞭起見,整個 BigDecimal 方法的描述中都使用了僞代碼。僞代碼表達式 (i + j) 是
 *  “其值爲 BigDecimal i 加 BigDecimal j 的 BigDecimal”的簡寫。
 *  僞代碼表達式 (i == j) 是“當且僅當 BigDecimal i 表示與 BigDecimal j 相同的值時,則爲 true”的簡寫。
 *  可以類似地解釋其他僞代碼表達式。方括號用於表示特定的 BigInteger 和定義 BigDecimal 值的標度對;
 *  例如,[19, 2] 表示 BigDecimal 在數值上等於 0.19,標度是 2。 
 *  注:如果 BigDecimal 對象用作 SortedMap 中的鍵或 SortedSet 中的元素,則應特別小心,
 *  因爲 BigDecimal 的自然排序與 equals 方法不一致。
 */
public class BigDecimal extends Number implements Comparable<BigDecimal> {
	/*
     * 繼承Number類提供將表示的數值轉換爲 byte、double、float、int、long 和 short 的方法。<br />
     * 實現Comparable接口,獲取到compareTo方法。
     */
	// BigDecimal的未scale的值,BigInteger是一個任意長度的整數(整數非標度值)
    private volatile BigInteger intVal;
 
	// BigDecimal的標度(小數點),輸入數除以10的scale次冪(32 位的整數標度)
    private int scale; // 注意:這可能有任何值,因此計算必須長時間進行
	// BigDecimal的精度(精度是非標度值的數字個數。)
    private transient int precision;
 
	// toString後緩存
    private transient String stringCache;
    // 標記值爲intCompact表示有效數字信息只能從intVal中獲得。
    static final long INFLATED = Long.MIN_VALUE;
	// 若BigDecimal的絕對值小於Long.MAX_VALUE,放在這個變量中
    private transient long intCompact;
    /*
     * 所有18位基數的10個字符串組成一個長字符串;
     * 不是所有的19位字符串都可以
     */
    private static final int MAX_COMPACT_DIGITS = 18;
 
    private static final int MAX_BIGINT_BITS = 62;
    // 序列化
    private static final long serialVersionUID = 6108874887143696463L;
 
    private static final ThreadLocal<StringBuilderHelper>
        threadLocalStringBuilderHelper = new ThreadLocal<StringBuilderHelper>() {
        @Override
        protected StringBuilderHelper initialValue() {
            return new StringBuilderHelper();
        }
    };
 
  //緩存0 ~ 10
    private static final BigDecimal zeroThroughTen[] = {
        new BigDecimal(BigInteger.ZERO,         0,  0, 1),
        new BigDecimal(BigInteger.ONE,          1,  0, 1),
        new BigDecimal(BigInteger.valueOf(2),   2,  0, 1),
        new BigDecimal(BigInteger.valueOf(3),   3,  0, 1),
        new BigDecimal(BigInteger.valueOf(4),   4,  0, 1),
        new BigDecimal(BigInteger.valueOf(5),   5,  0, 1),
        new BigDecimal(BigInteger.valueOf(6),   6,  0, 1),
        new BigDecimal(BigInteger.valueOf(7),   7,  0, 1),
        new BigDecimal(BigInteger.valueOf(8),   8,  0, 1),
        new BigDecimal(BigInteger.valueOf(9),   9,  0, 1),
        new BigDecimal(BigInteger.TEN,          10, 0, 2),
    };
 
  //緩存0 ~ 0E-15
    private static final BigDecimal[] ZERO_SCALED_BY = {
        zeroThroughTen[0],
        new BigDecimal(BigInteger.ZERO, 0, 1, 1),
        new BigDecimal(BigInteger.ZERO, 0, 2, 1),
        new BigDecimal(BigInteger.ZERO, 0, 3, 1),
        new BigDecimal(BigInteger.ZERO, 0, 4, 1),
        new BigDecimal(BigInteger.ZERO, 0, 5, 1),
        new BigDecimal(BigInteger.ZERO, 0, 6, 1),
        new BigDecimal(BigInteger.ZERO, 0, 7, 1),
        new BigDecimal(BigInteger.ZERO, 0, 8, 1),
        new BigDecimal(BigInteger.ZERO, 0, 9, 1),
        new BigDecimal(BigInteger.ZERO, 0, 10, 1),
        new BigDecimal(BigInteger.ZERO, 0, 11, 1),
        new BigDecimal(BigInteger.ZERO, 0, 12, 1),
        new BigDecimal(BigInteger.ZERO, 0, 13, 1),
        new BigDecimal(BigInteger.ZERO, 0, 14, 1),
        new BigDecimal(BigInteger.ZERO, 0, 15, 1),
    };
    // Long的一半。MIN_VALUE & Long.MAX_VALUE。
    private static final long HALF_LONG_MAX_VALUE = Long.MAX_VALUE / 2;
    private static final long HALF_LONG_MIN_VALUE = Long.MIN_VALUE / 2;
 
    // 常量
    // 值爲 0,標度爲 0。 
    public static final BigDecimal ZERO =
        zeroThroughTen[0];
 
    // 值爲 1,標度爲 0。
    public static final BigDecimal ONE =
        zeroThroughTen[1];
 
    // 值爲 10,標度爲 0。
    public static final BigDecimal TEN =
        zeroThroughTen[10];
 
    // 構造器
    /**
     * 受信任的包私有構造函數。可信僅僅意味着如果val是INFLATED,intVal不可能爲空,如果intVal爲空,val不可能是INFLATED。
     * @param intVal	BigInteger的數值
     * @param val	long的數值
     * @param scale	標度
     * @param prec	精度
     */
    BigDecimal(BigInteger intVal, long val, int scale, int prec) {
        this.scale = scale;
        this.precision = prec;
        this.intCompact = val;
        this.intVal = intVal;
    }
 
    /**
     * 將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列,同時允許指定子數組。 
     * 注意,如果字符數組中已經提供字符的序列,則使用此構造方法要比將 char 數組轉換爲字符串並使用 BigDecimal(String) 構造方法更快。 
     * @param in	作爲源字符的 char 數組
     * @param offset	要檢查的數組中的第一個字符
     * @param len	要考慮的字符數
     */
    public BigDecimal(char[] in, int offset, int len) {
        // 防止長度過大。
        if (offset+len > in.length || offset < 0)
            throw new NumberFormatException();
        /*
         * 這是BigDecimal構造函數的主字符串;
         * 所有傳入字符串都在這裏結束;
         * 它使用顯式(內聯)解析來提高速度,併爲非緊湊情況生成最多一箇中間(臨時)對象(char[]數組)。
         */
 
        // 對所有字段值使用局部變量,直到完成
        int prec = 0;                 // BigDecimal的數字的長度
        int scl = 0;                  // BigDecimal的標度
        long rs = 0;                  // intCompact值
        BigInteger rb = null;         // BigInteger的值
 
        // 使用數組邊界檢查來處理太長、len == 0、錯誤偏移等等。
        try {
        	// 符號的處理
            boolean isneg = false;          // '+'爲false,'-'爲true
            if (in[offset] == '-') {    // 第一個字符爲'-'
                isneg = true;              
                offset++;
                len--;
            } else if (in[offset] == '+') {// 第一個字符爲'+'
                offset++;
                len--;
            }
 
            // 數字有效部分
            boolean dot = false;             //當有“.”時爲真。
            int cfirst = offset;             // 記錄integer的起始點
            long exp = 0;                    // exponent
            char c;                          // 當前字符
 
            boolean isCompact = (len <= MAX_COMPACT_DIGITS);
 
            char coeff[] = isCompact ? null : new char[len];// 大於18位是BigInteger,創建數組
            int idx = 0;
 
            for (; len > 0; offset++, len--) {
                c = in[offset];
                // 有數字,確定c(Unicode 代碼點)是否爲數字
                if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
                    // 第一個緊化情況,我們不需要保留字符我們可以就地計算值。
                    if (isCompact) { // 非BigInteger數值
                    	// 獲取使用10進制的字符 c 的數值
                        int digit = Character.digit(c, 10);
                        if (digit == 0) {// 爲 0
                            if (prec == 0)
                                prec = 1;
                            else if (rs != 0) {
                                rs *= 10;
                                ++prec;
                            }// 否則,數字爲冗餘前導零
                        } else { // 非0
                            if (prec != 1 || rs != 0)
                                ++prec; // 如果前面加0,則prec不變
                            rs = rs * 10 + digit;
                        }
                    } else {// the unscaled value可能是一個BigInteger對象。
                        if (c == '0' || Character.digit(c, 10) == 0) {// 爲0
                            if (prec == 0) {
                                coeff[idx] = c;
                                prec = 1;
                            } else if (idx != 0) {
                                coeff[idx++] = c;
                                ++prec;
                            } // 否則c一定是多餘的前導零
                        } else {
                            if (prec != 1 || idx != 0)
                                ++prec; // 如果前面加0,則prec不變
                            coeff[idx++] = c;
                        }
                    }
                    if (dot)// 如果有小數點
                        ++scl;
                    continue;
                }
                // 當前字符等於小數點
                if (c == '.') {
                    // have dot
                    if (dot)         // 存在兩個小數點
                        throw new NumberFormatException();
                    dot = true;
                    continue;
                }
                // exponent 預期
                if ((c != 'e') && (c != 'E'))
                    throw new NumberFormatException();
                offset++;
                c = in[offset];
                len--;
                boolean negexp = (c == '-'); // 當前字符是否爲'-'
                if (negexp || c == '+') { // 爲符號
                    offset++;
                    c = in[offset];
                    len--;
                }
                if (len <= 0)    // 沒有 exponent 數字
                    throw new NumberFormatException();
                // 跳過exponent中的前導零 
                while (len > 10 && Character.digit(c, 10) == 0) {
                    offset++;
                    c = in[offset];
                    len--;
                }
                if (len > 10) // 太多非零 exponent 數字
                    throw new NumberFormatException();
                // c 現在是 exponent的第一個數字
                for (;; len--) {
                    int v;
                    if (c >= '0' && c <= '9') {
                        v = c - '0';
                    } else {
                        v = Character.digit(c, 10);
                        if (v < 0)           // 非數字
                            throw new NumberFormatException();
                    }
                    exp = exp * 10 + v;
                    if (len == 1)
                        break;               // 最終字符
                    offset++;
                    c = in[offset];
                }
                if (negexp)                 // 當前字符爲'-',取相反數
                    exp = -exp;
                // 下一個測試需要向後兼容性
                if ((int)exp != exp)         // 溢出
                    throw new NumberFormatException();
                break;                      
            }
            // 這裏沒有字符了
            if (prec == 0)              // 沒有發現數字
                throw new NumberFormatException();
            // 如果exp不爲零,調整標度。
            if (exp != 0) {                 // 有顯著的exponent
                // 不能調用基於正確的字段值的checkScale
                long adjustedScale = scl - exp;
                if (adjustedScale > Integer.MAX_VALUE ||
                    adjustedScale < Integer.MIN_VALUE)
                    throw new NumberFormatException("Scale out of range.");
                scl = (int)adjustedScale;
            }
            // 從precision中刪除前導零(數字計數)
            if (isCompact) {
                rs = isneg ? -rs : rs;
            } else {
                char quick[];
                if (!isneg) {
                    quick = (coeff.length != prec) ?
                        Arrays.copyOf(coeff, prec) : coeff;
                } else {
                    quick = new char[prec + 1];
                    quick[0] = '-';
                    System.arraycopy(coeff, 0, quick, 1, prec);
                }
                rb = new BigInteger(quick);
                // 獲取rb(BigInteger)的compact值。
                rs = compactValFor(rb);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new NumberFormatException();
        } catch (NegativeArraySizeException e) {
            throw new NumberFormatException();
        }
        this.scale = scl;
        this.precision = prec;
        this.intCompact = rs;
        this.intVal = (rs != INFLATED) ? null : rb;
    }
 
    /**
     * 將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列,同時允許指定子數組,並根據上下文設置進行舍入。 
     * 注意,如果字符數組中已經提供字符的序列,則使用此構造方法要比將 char 數組轉換爲字符串並使用 BigDecimal(String) 構造方法更快。
     * @param in	作爲源字符的 char 數組
     * @param offset	要檢查的數組中的第一個字符
     * @param len	要考慮的字符數
     * @param mc	要使用的上下文
     */
    public BigDecimal(char[] in, int offset, int len, MathContext mc) {
        this(in, offset, len);
        if (mc.precision > 0) // 精度大於0
            roundThis(mc);  // 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    /**
     * 將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列。 
     * 注意,如果字符序列已經可以作爲一個字符數組使用,則使用此構造方法要比將 char 數組轉換爲字符串並使用 BigDecimal(String) 構造方法更快。 
     * @param in	作爲源字符的 char 數組
     */
    public BigDecimal(char[] in) {
        this(in, 0, in.length);
    }
 
    /**
     * 將 BigDecimal 的字符數組表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符序列(根據上下文設置進行舍入)。 
     * 注意,如果字符序列已經可以作爲一個字符數組使用,則使用此構造方法要比將 char 數組轉換爲字符串並使用 BigDecimal(String) 構造方法更快。 
     * @param in	作爲源字符的 char 數組
     * @param mc	要使用的上下文
     */
    public BigDecimal(char[] in, MathContext mc) {
        this(in, 0, in.length, mc);
    }
 
    /**
     * 將 BigDecimal 的字符串表示形式轉換爲 BigDecimal。字符串表示形式由可選符號 '+' ('\u002B') 或 '-' ('\u002D') 組成,
     * 後跟零或多個十進制數字(“整數”)的序列,可以選擇後跟一個小數,也可以選擇後跟一個指數。 
     * 該小數由小數點以及後跟的零或更多十進制數字組成。字符串必須至少包含整數或小數部分中的一個數字。由符號、整數和小數部分組成的數字稱爲有效位數。 
     * 指數由字符 'e'('\u0065') 或 'E' ('\u0045') 以及後跟的一個或多個十進制數字組成。
     * 指數的值必須位於 Integer.MAX_VALUE (Integer.MIN_VALUE+1) 和 Integer.MAX_VALUE(包括)之間。
     * 
     * 注:對於不是 float、double NaN 和 ±Infinity 的值,此構造方法與 Float.toString(float) 和 Double.toString(double) 返回的值兼容。
     * 這通常是將 float 或 double 轉換爲 BigDecimal 的首選方法,因爲它不會遇到 BigDecimal(double) 構造方法的不可預知問題。 
     * @param val	BigDecimal 的字符串表示形式
     */
    public BigDecimal(String val) {
        this(val.toCharArray(), 0, val.length());
    }
 
    /**
     * 將 BigDecimal 的字符串表示形式轉換爲 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字符串(按照上下文設置進行舍入)。 
     * @param val	BigDecimal 的字符串表示形式。
     * @param mc	要使用的上下文。 
     */
    public BigDecimal(String val, MathContext mc) {
        this(val.toCharArray(), 0, val.length());
        if (mc.precision > 0)// 精度大於0
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    /**
     * 將 double 轉換爲 BigDecimal,後者是 double 的二進制浮點值準確的十進制表示形式。返回的 BigDecimal 的標度是使 (10的scale次冪 × val) 爲整數的最小值。 
     * 注: 
     * 1、此構造方法的結果有一定的不可預知性。有人可能認爲在 Java 中寫入 new BigDecimal(0.1) 所創建的 BigDecimal 正好等於 0.1(非標度值 1,其標度爲 1),
     * 但是它實際上等於 0.1000000000000000055511151231257827021181583404541015625。
     * 這是因爲 0.1 無法準確地表示爲 double(或者說對於該情況,不能表示爲任何有限長度的二進制小數)。這樣,傳入 到構造方法的值不會正好等於 0.1(雖然表面上等於該值)。 
     * 2、另一方面,String 構造方法是完全可預知的:寫入 new BigDecimal("0.1") 將創建一個 BigDecimal,它正好 等於預期的 0.1。因此,比較而言,通常建議優先使用 String 構造方法。 
     * 3、當 double 必須用作 BigDecimal 的源時,請注意,此構造方法提供了一個準確轉換;它不提供與以下操作相同的結果:
     * 先使用 Double.toString(double) 方法,然後使用 BigDecimal(String) 構造方法,將 double 轉換爲 String。要獲取該結果,請使用 static valueOf(double) 方法。 
     * @param val	要轉換爲 BigDecimal 的 double 值
     */
    public BigDecimal(double val) {
        if (Double.isInfinite(val) || Double.isNaN(val)) // 如果 val 爲無窮大或 NaN
            throw new NumberFormatException("Infinite or NaN");
        // 將double轉化爲符號、exponent和significand
        /*
         * 根據 IEEE 754 浮點雙精度格式 ("double format") 位佈局,返回val的表示形式。
         * 第 63 位(掩碼 0x8000000000000000L 選定的位)表示浮點數的符號。
         * 第 62-52 位(掩碼 0x7ff0000000000000L 選定的位)表示指數。
         * 第 51-0 位(掩碼 0x000fffffffffffffL 選定的位)表示浮點數的有效數字(有時也稱爲尾數)。 
         */
        long valBits = Double.doubleToLongBits(val);
        int sign = ((valBits >> 63)==0 ? 1 : -1);// 右移63位爲符號,判斷是0還是1
        int exponent = (int) ((valBits >> 52) & 0x7ffL);// 右移52位指數
        long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
                            : (valBits & ((1L<<52) - 1)) | (1L<<52));
        exponent -= 1075;
        // 這時候, val == sign * significand * 2**exponent.
        /*
         * 特殊情況零可以抑制無盡的規範化和虛假的規模計算。
         */
        if (significand == 0) {
            intVal = BigInteger.ZERO;
            intCompact = 0;
            precision = 1;
            return;
        }
 
        // 正常化
        while((significand & 1) == 0) {    //  i.e., significand 是偶數,significand等於0;&計算:兩位同爲1結果爲1,否則爲0
            significand >>= 1;
            exponent++;
        }
        // 計算intVal和scale
        long s = sign * significand;
        BigInteger b;
        if (exponent < 0) {// 指數小於0
            // 5 的-exponent次冪乘以s
            b = BigInteger.valueOf(5).pow(-exponent).multiply(s);
            scale = -exponent;
        } else if (exponent > 0) {// 指數大於0
        	// 2 的exponent次冪乘以s
            b = BigInteger.valueOf(2).pow(exponent).multiply(s);
        } else {
            b = BigInteger.valueOf(s);// 獲取s的 BigInteger值
        }
        intCompact = compactValFor(b);// 獲取val(BigInteger)的compact值。
        intVal = (intCompact != INFLATED) ? null : b;
    }
 
    /**
     * 將 double 轉換爲 BigDecimal(根據上下文設置進行舍入)。BigDecimal 的標度是使 (10的scale次冪 × val) 爲整數的最小值。 
     * 此構造方法的結果有一定的不可預知性,通常不建議使用它,請參見 BigDecimal(double) 構造方法下面的註釋。 
     * @param val	要轉換爲 BigDecimal 的 double 值
     * @param mc	要使用的上下文
     */
    public BigDecimal(double val, MathContext mc) {
        this(val);
        if (mc.precision > 0)// 精度大於0
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    /**
     * 將 BigInteger 轉換爲 BigDecimal。BigDecimal 的標度是零
     * @param val	要轉換爲 BigDecimal 的 BigInteger 值
     */
    public BigDecimal(BigInteger val) {
        intCompact = compactValFor(val);// 獲取val(BigInteger)的compact值。
        intVal = (intCompact != INFLATED) ? null : val;
    }
    /**
     * 將 BigInteger 轉換爲 BigDecimal(根據上下文設置進行舍入)。BigDecimal 的標度爲零。
     * @param val	要轉換爲 BigDecimal 的 BigInteger 值。
     * @param mc	要使用的上下文。 
     */
    public BigDecimal(BigInteger val, MathContext mc) {
        this(val);
        if (mc.precision > 0)// 精度大於0
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
    /**
     * 將 BigInteger 非標度值和 int 標度轉換爲 BigDecimal。BigDecimal 的值爲 (unscaledVal × 10的-scale冪)。 
     * @param unscaledVal	BigDecimal 的非標度值
     * @param scale	BigDecimal 的標度
     */
    public BigDecimal(BigInteger unscaledVal, int scale) {
        // 現在允許負標度
        this(unscaledVal);
        this.scale = scale;
    }
 
    /**
     * 將 BigInteger 非標度值和 int 標度轉換爲 BigDecimal(根據上下文設置進行舍入)。
     * BigDecimal 的值爲 (unscaledVal × 10-scale),它是根據 precision 和舍入模式設置進行舍入的。 
     * @param unscaledVal	BigDecimal 的非標度值
     * @param scale	BigDecimal 的標度
     * @param mc	要使用的上下文
     */
    public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
        this(unscaledVal);
        this.scale = scale;
        if (mc.precision > 0) // 精度大於0
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    /**
     * 將 int 轉換爲 BigDecimal。BigDecimal 的標度爲零
     * @param val 要轉換爲 BigDecimal 的 int 值
     */
    public BigDecimal(int val) {
        intCompact = val;
    }
 
    /**
     * 將 int 轉換爲 BigDecimal(根據上下文設置進行舍入)。在進行任何舍入之前,BigDecimal 的標度爲零
     * @param val	要轉換爲 BigDecimal 的 int 值
     * @param mc	要使用的上下文
     */
    public BigDecimal(int val, MathContext mc) {
        intCompact = val;
        if (mc.precision > 0)
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    /**
     * 將 long 轉換爲 BigDecimal。BigDecimal 的標度爲零。 
     * @param val	要轉換爲 BigDecimal 的 long 值
     */
    public BigDecimal(long val) {
        this.intCompact = val;
        this.intVal = (val == INFLATED) ? BigInteger.valueOf(val) : null;
    }
 
    /**
     * 將 long 轉換爲 BigDecimal(根據上下文設置進行舍入)。在進行任何舍入之前,BigDecimal 的標度爲零。 
     * @param val	要轉換爲 BigDecimal 的 long 值
     * @param mc	要使用的上下文。
     */
    public BigDecimal(long val, MathContext mc) {
        this(val);
        if (mc.precision > 0)
            roundThis(mc);// 根據MathContext設置將這個BigDecimal四捨五入
    }
 
    // 靜態工廠方法
 
    /**
     * 將 long 非標度值和 int 標度轉換爲 BigDecimal。提供的此“靜態工廠方法”優先於 (long, int) 構造方法,因爲前者允許重用經常使用的 BigDecimal 值。 
     * @param unscaledVal	BigDecimal 的非標度值
     * @param scale	BigDecimal 的標度
     * @return	其值爲 (unscaledVal × 10的-scale次冪) 的 BigDecimal
     */
    public static BigDecimal valueOf(long unscaledVal, int scale) {
        if (scale == 0)// 標度爲0,將 long 值轉換爲具有零標度的 BigDecimal。
            return valueOf(unscaledVal);
        else if (unscaledVal == 0) {
            if (scale > 0 && scale < ZERO_SCALED_BY.length)// 不超過緩存,直接返回緩存
                return ZERO_SCALED_BY[scale];
            else
                return new BigDecimal(BigInteger.ZERO, 0, scale, 1);
        }
        return new BigDecimal(unscaledVal == INFLATED ?
                              BigInteger.valueOf(unscaledVal) : null,
                              unscaledVal, scale, 0);
    }
    /**
     * 將 long 值轉換爲具有零標度的 BigDecimal。提供的此“靜態工廠方法”優先於 (long) 構造方法,因爲前者允許重用經常使用的 BigDecimal 值。 
     * @param val	BigDecimal 的值
     * @return	其值爲 val 的 BigDecimal
     */
    public static BigDecimal valueOf(long val) {
        if (val >= 0 && val < zeroThroughTen.length)// 不超過緩存,直接返回緩存
            return zeroThroughTen[(int)val];
        else if (val != INFLATED)
            return new BigDecimal(null, val, 0, 0);
        return new BigDecimal(BigInteger.valueOf(val), val, 0, 0);
    }
    /**
     * 使用 Double.toString(double) 方法提供的 double 規範的字符串表示形式將 double 轉換爲 BigDecimal。 
     * 注:這通常是將 double(或 float)轉化爲 BigDecimal 的首選方法,因爲返回的值等於從構造 BigDecimal(使用 Double.toString(double) 得到的結果)得到的值。 
     * @param val	要轉換爲 BigDecimal 的 double。 
     * @return	其值等於或約等於 val 值的 BigDecimal。 
     */
    public static BigDecimal valueOf(double val) {
        // 提醒:一個zero double返回“0.0”,因此我們不能快速路徑來使用常量zero。這一點可能非常重要,足以在以後證明工廠方法、緩存或一些私有常量是合理的。
        return new BigDecimal(Double.toString(val));
    }
 
    // 算術運算
    /**
     * 返回一個 BigDecimal,其值爲 (this + augend),其標度爲 max(this.scale(), augend.scale())。 
     * @param augend	將添加到此 BigDecimal 中的值。
     * @return	this + augend
     */
    public BigDecimal add(BigDecimal augend) {
        long xs = this.intCompact;// 整型數字表示的BigDecimal
        long ys = augend.intCompact;// 整型數字表示的BigDecimal
        //初始化        BigInteger的值,intVal爲BigDecimal的一個BigInteger類型的屬性
        BigInteger fst = (xs != INFLATED) ? null : this.intVal;
        BigInteger snd = (ys != INFLATED) ? null : augend.intVal;
        int rscale = this.scale;
 
        long sdiff = (long)rscale - augend.scale;//小數位數之差
        if (sdiff != 0) {// 取小數位數多的爲結果的小數位數
            if (sdiff < 0) {// 當前小數位數小於augend的小數位數
                int raise = checkScale(-sdiff);// 驗證-sdiff爲int
                rscale = augend.scale;
                // 計算xs * 10 ^ raise == INFLATED
                if (xs == INFLATED ||
                    (xs = longMultiplyPowerTen(xs, raise)) == INFLATED)
                	// 計算this* 10 ^ raise
                    fst = bigMultiplyPowerTen(raise);
            } else {// 當前小數位數大於等於augend的小數位數
                int raise = augend.checkScale(sdiff);// 取當前值
                // 計算ys * 10 ^ raise == INFLATED
                if (ys == INFLATED ||
                    (ys = longMultiplyPowerTen(ys, raise)) == INFLATED)
                	// 計算this* 10 ^ raise
                    snd = augend.bigMultiplyPowerTen(raise);
            }
        }
        if (xs != INFLATED && ys != INFLATED) {
            long sum = xs + ys;
            if ( (((sum ^ xs) & (sum ^ ys))) >= 0L)//判斷有無溢出
                return BigDecimal.valueOf(sum, rscale);//返回使用BigDecimal的靜態工廠方法得到的BigDecimal實例
        }
        if (fst == null)
            fst = BigInteger.valueOf(xs);//BigInteger的靜態工廠方法
        if (snd == null)
            snd = BigInteger.valueOf(ys);//BigInteger的靜態工廠方法
        BigInteger sum = fst.add(snd);
        // 返回通過其他構造方法得到的BigDecimal對象
        return (fst.signum == snd.signum) ?
            new BigDecimal(sum, INFLATED, rscale, 0) :
            new BigDecimal(sum, rscale);
    }
    /**
     * 返回其值爲 (this + augend) 的 BigDecimal(根據上下文設置進行舍入)。
     * 如果任一數字爲零,並且精度設置爲非零,則其他數字(必要時進行舍入)可以作爲結果。 
     * @param augend	將添加到此 BigDecimal 中的值
     * @param mc	要使用的上下文
     * @return	this + augend,必要時進行舍入
     */
    public BigDecimal add(BigDecimal augend, MathContext mc) {
        if (mc.precision == 0)
            return add(augend);
        BigDecimal lhs = this;
 
        // 如果值緊湊,可以優化
        // 如果當前對象的intVal爲空,分配適當的BigInteger給intVal字段,
        this.inflate();
        // 如果augend的intVal爲空,分配適當的BigInteger給intVal字段,
        augend.inflate();
        // 如果任意一個數字都是0,則使用另一個數字(如果需要的話)進行四捨五入和縮放。
        {
            boolean lhsIsZero = lhs.signum() == 0;// 判斷lhs 的值是否爲0
            boolean augendIsZero = augend.signum() == 0;// 判斷augend的值是否爲0
 
            if (lhsIsZero || augendIsZero) {
            	// 獲取lhs.scale()和augend.scale()中較大的一個
                int preferredScale = Math.max(lhs.scale(), augend.scale());
                BigDecimal result;
 
                if (lhsIsZero && augendIsZero) // 都爲0
                    return new BigDecimal(BigInteger.ZERO, 0, preferredScale, 0);
                // 判斷當前對象的值是否爲0,根據mc設置返回一個augend或者lhs四捨五入的BigDecimal對象
                result = lhsIsZero ? doRound(augend, mc) : doRound(lhs, mc);
 
                if (result.scale() == preferredScale) // 判斷結果標度是否爲最大
                    return result;
                else if (result.scale() > preferredScale) {// 結果標度大於最大
                    BigDecimal scaledResult =
                        new BigDecimal(result.intVal, result.intCompact,
                                       result.scale, 0);
                    // 從當前BigDecimal對象中刪除不重要的後置零,直到不能刪除更多的零爲止。
                    scaledResult.stripZerosToMatchScale(preferredScale);
                    return scaledResult;
                } else { // result.scale < preferredScale
                    int precisionDiff = mc.precision - result.precision();
                    int scaleDiff     = preferredScale - result.scale();
 
                    if (precisionDiff >= scaleDiff)// 精度差大於等於標度差
                        return result.setScale(preferredScale); // 可以達到目標規模
                    else
                        return result.setScale(result.scale() + precisionDiff);
                }
            }
        }
 
        long padding = (long)lhs.scale - augend.scale;
        if (padding != 0) {        // 標度不同; 需要對齊
        	// 返回一個長度爲2的數組,其條目的和等於lhs和augend參數的整數和。
            BigDecimal arg[] = preAlign(lhs, augend, padding, mc);
            // 匹配arg[0]和arg[1]的scales,以校準它們的最小有效數字
            matchScale(arg);
            lhs    = arg[0];
            augend = arg[1];
        }
 
        BigDecimal d = new BigDecimal(lhs.inflate().add(augend.inflate()),
                                      lhs.scale);
        // 根據mc設置返回一個d的四捨五入的BigDecimal對象
        return doRound(d, mc);
    }
 
    /**
     * 返回一個長度爲2的數組,其條目的和等於lhs和augend參數的整數和。
     * 
     * 如果數字的位置參數有足夠的差距,值較小的可以濃縮成一個“粘滯位”,如果最終結果的精度不包括小數量級操作數的高階數,則最終結果將以相同的方式進行四捨五入。
     * 
     * 注意,雖然嚴格來說這是一種優化,但它的實際應用範圍更廣。
     * 
     * 這對應於固定精度浮點加法器中的預移位操作;這個方法由於MathContext所決定的結果的可變精度而變得複雜。
     * 更細緻的操作可以實現較小幅度操作數上的“右偏移”,從而即使部分重疊的有效數也可以減少較小操作數的位數。
     * @param lhs	當前 BigDecimal 中的值
     * @param augend	將添加到此 BigDecimal 中的值
     * @param padding lhs.scale- padding.scale
     * @param mc	要使用的上下文
     * @return
     */
    private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend,
                                  long padding, MathContext mc) {
        assert padding != 0;
        BigDecimal big;
        BigDecimal small;
 
        if (padding < 0) {     // lhs is big;   augend is small
            big   = lhs;
            small = augend;
        } else {               // lhs is small; augend is big
            big   = augend;
            small = lhs;
        }
		/*
		 * 這是結果的ulp的估計尺度;它假設結果沒有一個真正的add(例如999 + 1 = > - 1000)或任何一個借位的減法取消(例如,100 - 1.2 = > 98.8)
		 */
        long estResultUlpScale = (long)big.scale - big.precision() + mc.precision;
 
        /*
         * big的低位是big.scale()。這是真的,不管大的規模是正的還是負的。
         * 小的高階位是small.scale - (small.precision() - 1)。
         */
        long smallHighDigitPos = (long)small.scale - small.precision() + 1;
        if (smallHighDigitPos > big.scale + 2 &&         // 大小不相交
            smallHighDigitPos > estResultUlpScale + 2) { // small 不可見
			small = BigDecimal
            small = BigDecimal.valueOf(small.signum(),
                                       this.checkScale(Math.max(big.scale, estResultUlpScale) + 3));
        }
 
		// 因爲加法是對稱的,所以在返回的操作數中保持輸入順序並不重要
        BigDecimal[] result = {big, small};
        return result;
    }
 
	/**
	 * 返回一個 BigDecimal,其值爲 (this - subtrahend),其標度爲 max(this.scale(), subtrahend.scale())。 
	 * @param subtrahend	從此 BigDecimal 減去的值
	 * @return	this - subtrahend
	 */
    public BigDecimal subtract(BigDecimal subtrahend) {
    	// 獲取當前對象,其值爲 (-subtrahend),其標度爲 subtrahend.scale()。 
        return add(subtrahend.negate());
    }
 
    /**
     * 返回其值爲 (this - subtrahend) 的 BigDecimal(根據上下文設置進行舍入)。 
     * 如果 subtrahend 爲零,則將其(必要時進行舍入)作爲結果。如果爲零,則該結果是 subtrahend.negate(mc)。 
     * @param subtrahend	從此 BigDecimal 減去的值
     * @param mc	要使用的上下文
     * @return	this - subtrahend,必要時進行舍入
     */
    public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
    	// 獲取當前對象,其值爲 (-subtrahend),其標度爲 subtrahend.scale()。 
        BigDecimal nsubtrahend = subtrahend.negate();
        if (mc.precision == 0)
            return add(nsubtrahend);
        // 在add()中共享特殊的四捨五入
        return add(nsubtrahend, mc);
    }
 
    /**
     * 返回一個 BigDecimal,其值爲 (this × multiplicand),其標度爲 (this.scale() + multiplicand.scale())。 
     * @param multiplicand	乘以此 BigDecimal 的值
     * @return	this * multiplicand
     */
    public BigDecimal multiply(BigDecimal multiplicand) {
        long x = this.intCompact;
        long y = multiplicand.intCompact;
        // 驗證(long)scale + multiplicand.scale爲int,並返回(long)scale + multiplicand.scale值
        int productScale = checkScale((long)scale + multiplicand.scale);
        // 可以做一個更聰明的檢查,將INFLATED的檢查合併到溢出計算中。
        if (x != INFLATED && y != INFLATED) {
            /*
             * 如果product不是溢出值,則繼續使用compact表示。如果x或y中的任何一個是INFLATED,product也應該被視爲溢出。
             * 在使用“Hacker's Delight”第2-12節中建議的溢出測試之前,我們使用精確信息進行快速檢查,
             * 以確定是否會發生溢出,因爲大多數cpu上的分區開銷很大。
             */
            long product = x * y;
            long prec = this.precision() + multiplicand.precision();
            if (prec < 19 || (prec < 21 && (y == 0 || product / y == x)))
            	// 將 product 非標度值和 productScale 標度轉換爲 BigDecimal
                return BigDecimal.valueOf(product, productScale);
            return new BigDecimal(BigInteger.valueOf(x).multiply(y), INFLATED,
                                  productScale, 0);
        }
        BigInteger rb;
        if (x == INFLATED && y == INFLATED)// 溢出
            rb = this.intVal.multiply(multiplicand.intVal);
        else if (x != INFLATED)// multiplicand.intVal * x
            rb = multiplicand.intVal.multiply(x);
        else// this.intVal * y
            rb = this.intVal.multiply(y);
        return new BigDecimal(rb, INFLATED, productScale, 0);
    }
    /**
     * 返回其值爲 (this × multiplicand) 的 BigDecimal(根據上下文設置進行舍入)。 
     * @param multiplicand	乘以此 BigDecimal 的值。
     * @param mc	要使用的上下文
     * @return	必要時舍入的 this * multiplicand。 
     */
    public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
        if (mc.precision == 0)
        	// this * multiplicand
            return multiply(multiplicand);
        // 根據mc設置返回一個 (this * multiplicand)四捨五入的BigDecimal對象
        return doRound(this.multiply(multiplicand), mc);
    }
 
    /**
     * 返回一個 BigDecimal,其值爲 (this / divisor),其標度爲指定標度。如果必須執行舍入,以生成具有指定標度的結果,則應用指定的舍入模式。 
     * 相對於此遺留方法,應優先使用新的 divide(BigDecimal, int, RoundingMode) 方法。 
     * @param divisor	此 BigDecimal 要除以的值
     * @param scale	要返回的 BigDecimal 商的標度
     * @param roundingMode	要應用的舍入模式
     * @return	this / divisor 
     */
    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
        /*
         * 注意:這個方法*必須*返回一個新對象,因爲divideAndRound使用divide生成一個值,然後修改該值的標度。
         */
        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
        	// 如果 roundingMode 不表示一個有效的舍入模式
            throw new IllegalArgumentException("Invalid rounding mode");
        /*
         * 重新縮放被除數或除數(可“放大”以產生正確縮放的商的任何一種)。
         * 注意檢測超出範圍的標度
         */
        BigDecimal dividend = this;
     // 驗證(long)scale + divisor.scale爲int,並判斷(long)scale + divisor.scale值 > this.scale
        if (checkScale((long)scale + divisor.scale) > this.scale)
            dividend = this.setScale(scale + divisor.scale, ROUND_UNNECESSARY);
        else// 獲取一個BigDecimal,其標度爲指定值。
            divisor = divisor.setScale(checkScale((long)this.scale - scale),
                                       ROUND_UNNECESSARY);
        // 內部除法計算
        return divideAndRound(dividend.intCompact, dividend.intVal,
                              divisor.intCompact, divisor.intVal,
                              scale, roundingMode, scale);
    }
 
    /**
     * 內部用於除法運算。
     * 被除數和除數以long格式和BigInteger格式傳遞。
     * 返回的BigDecimal對象是其標度設置爲傳入的標度的商。如果餘數不爲零,則根據在roundingMode中傳遞的值進行四捨五入。
     * 此外,如果餘數爲0,並且最後一個參數preferredScale不等於scale,則會刪除結果的尾隨零以匹配preferredScale。
     * @param ldividend	被除數的intCompact
     * @param bdividend	被除數的intVal
     * @param ldivisor	除數的intCompact
     * @param bdivisor	除數的intVal
     * @param scale	要返回的 BigDecimal 商的標度
     * @param roundingMode	要應用的舍入模式
     * @param preferredScale	要返回的 BigDecimal 商的標度
     * @return	返回的BigDecimal對象是其標度設置爲傳入的標度的商
     */
    private static BigDecimal divideAndRound(long ldividend, BigInteger bdividend,
                                             long ldivisor,  BigInteger bdivisor,
                                             int scale, int roundingMode,
                                             int preferredScale) {
        boolean isRemainderZero;       // 記錄餘數是否爲零
        int qsign;                     // ldividend和ldivisor符號相同爲1,否則爲-1
        long q = 0, r = 0;             // 存儲商 & 餘數 用long類型
        MutableBigInteger mq = null;   // 存儲商
        MutableBigInteger mr = null;   // 存儲餘數
        MutableBigInteger mdivisor = null;
        boolean isLongDivision = (ldividend != INFLATED && ldivisor != INFLATED);
        if (isLongDivision) {// 商和餘數處理
            q = ldividend / ldivisor; // 獲取商
            if (roundingMode == ROUND_DOWN && scale == preferredScale)
                return new BigDecimal(null, q, scale, 0);
            r = ldividend % ldivisor; // 獲取餘數
            isRemainderZero = (r == 0);
            qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
        } else {
            if (bdividend == null)
                bdividend = BigInteger.valueOf(ldividend);
			// 下降到mutable中,以便進行更快速的餘數檢查
            MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
            mq = new MutableBigInteger();
            if (ldivisor != INFLATED) {
				// 內部用於計算此div ldivisor的商,並將商放在提供的mq對象中,然後返回餘數。
                r = mdividend.divide(ldivisor, mq);
                isRemainderZero = (r == 0);
                qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
            } else {
                mdivisor = new MutableBigInteger(bdivisor.mag);
				// 內部用於計算此div mdivisor的商,並將商放在提供的mq對象中,然後返回餘數。
                mr = mdividend.divide(mdivisor, mq);
                isRemainderZero = mr.isZero();// 判斷是否爲0
                qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
            }
        }
		// 餘數非0處理
        boolean increment = false;
        if (!isRemainderZero) {// 餘數非0
            int cmpFracHalf;
			/* 視情況而定 */
            if (roundingMode == ROUND_UNNECESSARY) { //斷言請求的操作具有精確的結果,因此不需要舍入
                throw new ArithmeticException("Rounding necessary");
            } else if (roundingMode == ROUND_UP) {      // 舍入遠離零的舍入模式
                increment = true;
            } else if (roundingMode == ROUND_DOWN) {    // 接近零的舍入模式
                increment = false;
            } else if (roundingMode == ROUND_CEILING) { // 接近正無窮大的舍入模式 Towards +infinity
                increment = (qsign > 0);
            } else if (roundingMode == ROUND_FLOOR) {   // 接近負無窮大的舍入模式 Towards -infinity
                increment = (qsign < 0);
            } else {
                if (isLongDivision || ldivisor != INFLATED) {
                    if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
                        cmpFracHalf = 1;    // 2 * r 不能符合 long
                    } else {
						// 判斷2 * r和ldivisor的絕對值的大小
                        cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
                    }
                } else {
                    cmpFracHalf = mr.compareHalf(mdivisor);// 將其與mdivisor的一半進行比較。
                }
                if (cmpFracHalf < 0)
                    increment = false;     // 更接近高位
                else if (cmpFracHalf > 0)  // 更接近低位
                    increment = true;
                else if (roundingMode == ROUND_HALF_UP)// 舍入遠離零的舍入模式
                    increment = true;
                else if (roundingMode == ROUND_HALF_DOWN)// 接近零的舍入模式
                    increment = false;
                else  // roundingMode == ROUND_HALF_EVEN, true iff商是奇數
                    increment = isLongDivision ? (q & 1L) != 0L : mq.isOdd();
            }
        }
		/*
		 * 最終的res處理
		 */
        BigDecimal res;
        if (isLongDivision)
            res = new BigDecimal(null, (increment ? q + qsign : q), scale, 0);
        else {
            if (increment)
                mq.add(MutableBigInteger.ONE);
			// 將mq轉換爲具有qsign和scale的BigDecimal對象。
            res = mq.toBigDecimal(qsign, scale);
        }
        if (isRemainderZero && preferredScale != scale)
			// 從當前BigDecimal對象中刪除不重要的後置零,直到不能刪除更多的零爲止。
            res.stripZerosToMatchScale(preferredScale);
        return res;
    }
	/**
	 * 返回一個 BigDecimal,其值爲 (this / divisor),其標度爲指定標度。
	 * 如果必須執行舍入,以生成具有指定標度的結果,則應用指定的舍入模式。 
	 * 相對於此遺留方法,應優先使用新的 divide(BigDecimal, int, RoundingMode) 方法。 
	 * @param divisor	此 BigDecimal 要除以的值
	 * @param scale	要返回的 BigDecimal 商的標度
	 * @param roundingMode	要應用的舍入模式
	 * @return	this / divisor 
	 */
    public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
        return divide(divisor, scale, roundingMode.oldMode);
    }
 
    /**
     * 返回一個 BigDecimal,其值爲 (this / divisor),其標度爲 this.scale()。
     * 如果必須執行舍入,以生成具有給定標度的結果,則應用指定的舍入模式。 
     * 相對於此遺留方法,應優先使用新的 divide(BigDecimal, RoundingMode) 方法。 
     * @param divisor	此 BigDecimal 要除以的值。
     * @param roundingMode	 要應用的舍入模式
     * @return	this / divisor 
     */
    public BigDecimal divide(BigDecimal divisor, int roundingMode) {
            return this.divide(divisor, scale, roundingMode);
    }
 
    /**
     * 返回一個 BigDecimal,其值爲 (this / divisor),其標度爲 this.scale()。
     * 如果必須執行舍入,以生成具有給定標度的結果,則應用指定的舍入模式。 
     * @param divisor	此 BigDecimal 要除以的值
     * @param roundingMode	要應用的舍入模式
     * @return	this / divisor 
     */
    public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
        return this.divide(divisor, scale, roundingMode.oldMode);
    }
 
    /**
     * 返回一個 BigDecimal,其值爲 (this / divisor),其首選標度爲 (this.scale() - divisor.scale());
     * 如果無法表示準確的商值(因爲它有無窮的十進制擴展),則拋出 ArithmeticException。 
     * @param divisor	此 BigDecimal 要相除的值
     * @return	this / divisor 
     */
    public BigDecimal divide(BigDecimal divisor) {
        /*
         * 先處理零情況。
         */
        if (divisor.signum() == 0) {   // x/0
            if (this.signum() == 0)    // 0/0
                throw new ArithmeticException("Division undefined");  // NaN
            throw new ArithmeticException("Division by zero");
        }
 
        // 計算優先 scale
        // (long)this.scale - divisor.scale強轉爲int類型,判斷是否等於int類型後的值,若果是,返回int類型後的值,否則小於0,返回integer最小值,否則最大值
        int preferredScale = saturateLong((long)this.scale - divisor.scale);
        if (this.signum() == 0)        // 0/y
            return (preferredScale >= 0 &&
                    preferredScale < ZERO_SCALED_BY.length) ?
                ZERO_SCALED_BY[preferredScale] :
                BigDecimal.valueOf(0, preferredScale);
        else {
        	// 如果當前對象的intVal爲空,分配適當的BigInteger給intVal字段,
            this.inflate();
            divisor.inflate();
            /*
             * 如果this/divisor的商有一個終止小數展開,那麼展開的位數不能超過(a.precision() + ceil(10*b.precision)/3)位。
             * 因此,使用這種精度創建MathContext對象,並使用UNNECESSARY的舍入模式執行除法。
             */
            MathContext mc = new MathContext( (int)Math.min(this.precision() +
                                                            (long)Math.ceil(10.0*divisor.precision()/3.0),
                                                            Integer.MAX_VALUE),
                                              RoundingMode.UNNECESSARY);
            BigDecimal quotient;
            try {
            	// 返回一個 BigDecimal,其值爲 (this / divisor),其標度爲 this.scale()。 
                quotient = this.divide(divisor, mc);
            } catch (ArithmeticException e) {
                throw new ArithmeticException("Non-terminating decimal expansion; " +
                                              "no exact representable decimal result.");
            }
 
            int quotientScale = quotient.scale();// 獲取quotient 的標度
            /*
             * divide(BigDecimal, mc)嘗試通過刪除後面的零來將商調整爲所需的商;由於精確divide method沒有明確的數字限制,我們也可以加上0。
             */
            if (preferredScale > quotientScale)
            	// 返回 BigDecimal,其標度爲preferredScale,其非標度值通過此 BigDecimal 的非標度值乘以或除以十的適當次冪來確定,以維護其總值
                return quotient.setScale(preferredScale, ROUND_UNNECESSARY);
 
            return quotient;
        }
    }
 
    /**
     * 返回其值爲 (this / divisor) 的 BigDecimal(根據上下文設置進行舍入)。 
     * @param divisor	此 BigDecimal 要除以的值
     * @param mc	要使用的上下文
     * @return	this / divisor,必要時進行舍入
     */
    public BigDecimal divide(BigDecimal divisor, MathContext mc) {
        int mcp = mc.precision;
        if (mcp == 0)
        	// 返回一個 BigDecimal,其值爲 (this / divisor),其首選標度爲 (this.scale() - divisor.scale());
            return divide(divisor);
 
        BigDecimal dividend = this;
        long preferredScale = (long)dividend.scale - divisor.scale;
        /*
         * 現在計算答案。我們使用現有的divide-and-round method,但是當這輪進行縮放時,我們必須對這裏的值進行標準化以達到預期的結果。
         * 對於x/y,我們首先處理y=0和x=0,然後對x和y進行標準化,得到具有以下約束條件的x'和y':
         * 	(a) 0.1 <= x' < 1
         *  (b)  x' <= y' < 10*x'
         * 將x'/y'除以所需的scale設置爲mc.precision,則會得到範圍0.1到1的四捨五入結果,
         * 精確到正確的數字數(如果結果爲1.000,則除外……)當x=y,或者四捨五入超過1。case會適當地減少到1。
         */
        if (divisor.signum() == 0) {      // x/0
            if (dividend.signum() == 0)    // 0/0
                throw new ArithmeticException("Division undefined");  // NaN
            throw new ArithmeticException("Division by zero");
        }
        if (dividend.signum() == 0)        // 0/y
            return new BigDecimal(BigInteger.ZERO, 0,
                                  saturateLong(preferredScale), 1);
 
        // 使被除數和除數標準化,使兩者均爲[0.1,0.999…]
        // 返回此 BigDecimal 的精度
        int xscale = dividend.precision();
        int yscale = divisor.precision();
        dividend = new BigDecimal(dividend.intVal, dividend.intCompact,
                                  xscale, xscale);
        divisor = new BigDecimal(divisor.intVal, divisor.intCompact,
                                 yscale, yscale);
        if (dividend.compareMagnitude(divisor) > 0) // 滿足約束(b)
            yscale = divisor.scale -= 1;            // [that is, divisor *= 10]
 
        /*
         * 爲了確定除法是否產生準確的結果,我們避免調用上述divide method。'除法'保存返回的BigDecimal對象,該對象的比例將設置爲'scl'。
         */
        BigDecimal quotient;
        int scl = checkScale(preferredScale + yscale - xscale + mcp);
        if (checkScale((long)mcp + yscale) > xscale)
        	// 獲取一個BigDecimal,其標度爲指定值。
            dividend = dividend.setScale(mcp + yscale, ROUND_UNNECESSARY);
        else
            divisor = divisor.setScale(checkScale((long)xscale - mcp),
                                       ROUND_UNNECESSARY);
        // 調用內部除法運算
        quotient = divideAndRound(dividend.intCompact, dividend.intVal,
                                  divisor.intCompact, divisor.intVal,
                                  scl, mc.roundingMode.oldMode,
                                  checkScale(preferredScale));
        // 在這裏,僅影響1000000000的情況。
        quotient = doRound(quotient, mc);
 
        return quotient;
    }
 
    /**
     * 返回 BigDecimal,其值爲向下舍入所得商值 (this / divisor) 的整數部分。該結果的首選標度爲 (this.scale() - divisor.scale())。 
     * @param divisor	此 BigDecimal 要除以的值
     * @return	this / divisor 的整數部分
     */
    public BigDecimal divideToIntegralValue(BigDecimal divisor) {
        // 計算優先 scale
    	// (long)this.scale - divisor.scale強轉爲int類型,判斷是否等於int類型後的值,若果是,返回int類型後的值,否則小於0,返回integer最小值,否則最大值
        int preferredScale = saturateLong((long)this.scale - divisor.scale);
        if (this.compareMagnitude(divisor) < 0) {
            // 更快 when this << divisor
            return BigDecimal.valueOf(0, preferredScale);
        }
 
        if(this.signum() == 0 && divisor.signum() != 0)
        	// 獲取一個BigDecimal,其標度爲指定值。
            return this.setScale(preferredScale, ROUND_UNNECESSARY);
 
        // 執行一個除法,用足夠的數字四捨五入到一個正確的整數值;然後去掉任何小數
 
        int maxDigits = (int)Math.min(this.precision() +
                                      (long)Math.ceil(10.0*divisor.precision()/3.0) +
                                      Math.abs((long)this.scale() - divisor.scale()) + 2,
                                      Integer.MAX_VALUE);
        // 返回其值爲 (this / divisor) 的 BigDecimal(根據上下文設置進行舍入)。 
        BigDecimal quotient = this.divide(divisor, new MathContext(maxDigits,
                                                                   RoundingMode.DOWN));
        if (quotient.scale > 0) {
        	// 獲取一個BigDecimal,其標度爲指定值。
            quotient = quotient.setScale(0, RoundingMode.DOWN);
         // 從當前BigDecimal對象中刪除不重要的後置零,直到不能刪除更多的零爲止。
            quotient.stripZerosToMatchScale(preferredScale);
        }
 
        if (quotient.scale < preferredScale) {
            // 如果需要,用零填充
            quotient = quotient.setScale(preferredScale, ROUND_UNNECESSARY);
        }
        return quotient;
    }
 
    /**
     * 返回 BigDecimal,其值爲 (this / divisor) 的整數部分。因爲準確商值的整數部分與舍入模式無關,所以舍入模式不影響此方法返回的值。
     * 該結果的首選標度是 (this.scale() - divisor.scale())。
     * 如果準確商值的整數部分需要的位數多於 mc.precision,則拋出 ArithmeticException。
     * @param divisor	此 BigDecimal 要相除的值
     * @param mc	要使用的上下文
     * @return	this / divisor 的整數部分
     */
    public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
        if (mc.precision == 0 ||                        // 確切的結果
            (this.compareMagnitude(divisor) < 0) )      // 零結果
            return divideToIntegralValue(divisor);
        // 計算優先scale
        int preferredScale = saturateLong((long)this.scale - divisor.scale);
 
        /*
         * 對mc.precision數字執行普通除法。如果餘數的絕對值小於除數,則商的整數部分適合mc.precision數字。
         * 接下來,從商中刪除任何小數,並將scale調整爲首選值。
         */
        BigDecimal result = this.
            divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN));
 
        if (result.scale() < 0) {
            /*
             * 結果是一個整數。看商是否表示精確商的整數部分;如果是,計算出來的餘數將小於除數。
             */
            BigDecimal product = result.multiply(divisor);
            // 如果商是整數值,|dividend-product| < |divisor|.
            if (this.subtract(product).compareMagnitude(divisor) >= 0) {
            	// 如果 mc.precision > 0,並且該結果需要的精度大於 mc.precision。
                throw new ArithmeticException("Division impossible");
            }
        } else if (result.scale() > 0) {
            /*
             * 商的整數部分將適合於precision數字;重新計算商的scale 0,以避免雙舍入,然後嘗試調整,如果需要。
             */
            result = result.setScale(0, RoundingMode.DOWN);
        }
        // else result.scale() == 0;
 
        int precisionDiff;
        if ((preferredScale > result.scale()) &&
            (precisionDiff = mc.precision - result.precision()) > 0) {
            return result.setScale(result.scale() +
                                   Math.min(precisionDiff, preferredScale - result.scale) );
        } else {
        	// 從當前BigDecimal對象中刪除不重要的後置零,直到不能刪除更多的零爲止。
            result.stripZerosToMatchScale(preferredScale);
            return result;
        }
    }
 
    /**
     * 返回其值爲 (this % divisor) 的 BigDecimal。 
     * 餘數由 this.subtract(this.divideToIntegralValue(divisor).multiply(divisor)) 給出。注意,這不是模操作(結果可以爲負)。 
     * @param divisor	此 BigDecimal 要除以的值
     * @return	this % divisor
     */
    public BigDecimal remainder(BigDecimal divisor) {
        BigDecimal divrem[] = this.divideAndRemainder(divisor);
        return divrem[1];
    }
 
 
    /**
     * 返回其值爲 (this % divisor) 的 BigDecimal(根據上下文設置進行舍入)。
     * MathContext 設置會影響用於計算餘數的隱式除法。餘數計算本身要進行準確的定義。
     * 因此,餘數包含的數字個數可能多於 mc.getPrecision()。
     *  餘數由 this.subtract(this.divideToIntegralValue(divisor, mc).multiply(divisor)) 給出。注意,這不是模操作(結果可以爲負)。 
     * @param divisor	此 BigDecimal 要相除的值
     * @param mc	要使用的上下文
     * @return	this % divisor,必要時進行舍入
     */
    public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
        BigDecimal divrem[] = this.divideAndRemainder(divisor, mc);
        return divrem[1];
    }
 
    /**
     * 返回由兩個元素組成的 BigDecimal 數組,該數組包含 divideToIntegralValue 的結果,後跟對兩個操作數計算所得到的 remainder。 
     * 注意,如果同時需要整數商和餘數,則此方法比分別使用 divideToIntegralValue 和 remainder 方法更快速,因爲相除僅需執行一次。
     * @param divisor	此 BigDecimal 要相除的值和計算的餘數
     * @return	由兩個元素組成的 BigDecimal 數組:商值(divideToIntegralValue 的結果)是初始元素,餘數是最終元素
     */
    public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
        // 我們用恆等式x = i * y + r來確定r
        BigDecimal[] result = new BigDecimal[2];
        // 返回 BigDecimal,其值爲向下舍入所得商值 (this / divisor) 的整數部分。該結果的首選標度爲 (this.scale() - divisor.scale())。 
        result[0] = this.divideToIntegralValue(divisor);
        // 返回一個 BigDecimal,其值爲 (this - result[0].multiply(divisor)),其標度爲 max(this.scale(), result[0].multiply(divisor).scale())。
        result[1] = this.subtract(result[0].multiply(divisor));
        return result;
    }
 
    /**
     * 返回由兩個元素組成的 BigDecimal 數組,該數組包含 divideToIntegralValue 的結果,後跟根據上下文設置對兩個操作數進行舍入計算所得到的 remainder 的結果。 
     * 注意,如果同時需要整數商和餘數,則此方法比分別使用 divideToIntegralValue 和 remainder 方法更快速,因爲相除僅需執行一次。 
     * @param divisor	此 BigDecimal 要相除的值和計算的餘數
     * @param mc	要使用的上下文
     * @return	由兩個元素組成的 BigDecimal 數組:商值(divideToIntegralValue 的結果)是初始元素,餘數是最終元素
     */
    public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
        if (mc.precision == 0)// 返回由兩個元素組成的 BigDecimal 數組,
            return divideAndRemainder(divisor);
 
        BigDecimal[] result = new BigDecimal[2];
        BigDecimal lhs = this;
        // 返回 BigDecimal,其值爲 (this / divisor) 的整數部分。
        result[0] = lhs.divideToIntegralValue(divisor, mc);
        // 返回一個 BigDecimal,其值爲 (this - result[0].multiply(divisor)),其標度爲 max(this.scale(), result[0].multiply(divisor).scale())。 
        result[1] = lhs.subtract(result[0].multiply(divisor));
        return result;
    }
 
    /**
     * 返回其值爲 (this的n次冪) 的 BigDecimal,準確計算該冪,使其具有無限精度。 
     * 參數 n 必須在 0 到 999999999(包括)之間。ZERO.pow(0) 返回 ONE。 注意,未來版本可能會擴展此方法允許的指數範圍。
     * @param n	此 BigDecimal 的冪
     * @return	this的n次冪
     */
    public BigDecimal pow(int n) {
        if (n < 0 || n > 999999999)// 如果 n 超出範圍
            throw new ArithmeticException("Invalid operation");
        // 如果結果爲溢流/欠流,則無需計算pow(n)。不要試圖支持“超常”的數字。
        int newScale = checkScale((long)scale * n);
        // 如果當前對象的intVal爲空,分配適當的BigInteger給intVal字段,
        this.inflate();
        return new BigDecimal(intVal.pow(n), newScale);
    }
 
 
    /**
     * 返回其值爲 (thisn) 的 BigDecimal。當前實現使用的是 ANSI 標準 X3.274-1996 中定義的核心算法(根據上下文設置進行舍入)。
     * 一般情況下,返回的數值在具有選擇精度的精確數值的兩個 ulp 中。注意,未來版本可以使用不同的算法,以減少允許的錯誤範圍,並增加允許的指數範圍。 
     * X3.274-1996 算法爲: 
     * 	如果出現以下情況,則拋出 ArithmeticException 異常 
     * 		abs(n) > 999999999 
     * 		mc.precision == 0 且 n < 0 
     * 		mc.precision > 0 且 n 大於 mc.precision 
     * 	如果 n 爲零,則返回 ONE(即使 this 爲零),否則 
     * 		如果 n 爲正數,則通過重複的平方技術將此結果計算到一個累加器中。每個附帶累加器的乘法都使用與 mc 中相同的數學上下文設置,
     * 	        增加到 mc.precision + elength + 1 的精度除外,其中 elength 表示 n 中的十進制數字的個數。 
     * 		如果 n 爲負數,則將 n 視爲正數計算其結果;然後使用上面指定的工作精度,用一除以此值。 
     * 		然後將正數或負數的最終值舍入爲目標精度。 
     * @param n	此 BigDecimal 的冪。
     * @param mc	要使用的上下文。
     * @return	使用 ANSI 標準 X3.274-1996 算法的 this的n次冪 
     */
    public BigDecimal pow(int n, MathContext mc) {
        if (mc.precision == 0)
            return pow(n);
        if (n < -999999999 || n > 999999999)// 如果 n 超出範圍
            throw new ArithmeticException("Invalid operation");
        if (n == 0)// 如果 n 爲零,則返回 ONE(即使 this 爲零)
            return ONE;                      // x**0 == 1 in X3.274
        this.inflate();// 如果當前對象的intVal爲空,分配適當的BigInteger給intVal字段
        BigDecimal lhs = this;
        MathContext workmc = mc;          // 設置working
        int mag = Math.abs(n);                // 返回n的絕對值
        if (mc.precision > 0) {
 
            int elength = longDigitLength(mag); // 以數字表示的mag的絕對值的長度
            if (elength > mc.precision)        // X3.274規則
                throw new ArithmeticException("Invalid operation");
            // 構造一個新的 MathContext,它具有指定的精度(mc.precision + elength + 1)和舍入模式(mc.roundingMode)。 
            workmc = new MathContext(mc.precision + elength + 1,
                                      mc.roundingMode);
        }
        // 準備進行power計算…
        BigDecimal acc = ONE;           // accumulator
        boolean seenbit = false;        // 當我們看到1-bit的時候
        for (int i=1;;i++) {            // 對於每個bit [忽略上面bit]
            mag += mag;                 // 左進位 1 bit
            if (mag < 0) {             // 上面bit已設置
                seenbit = true;         // OK, 我們已關閉
                acc = acc.multiply(lhs, workmc); // acc=acc*x
            }
            if (i == 31)
                break;                  // 這是最後 1 bit
            if (seenbit)
                acc=acc.multiply(acc, workmc);   // acc=acc*acc [平方]
                // 否則,平方是沒有意義的
        }
        // 如果是- n,用工作精度計算倒數
        if (n<0)                          // [因此 mc.precision>0]
            acc=ONE.divide(acc, workmc);
        // 四捨五入到最後的精度和零
        // 根據mc設置返回一個acc的四捨五入的BigDecimal對象
        return doRound(acc, mc);
    }
 
    /**
     * 返回 BigDecimal,其值爲此 BigDecimal 的絕對值,其標度爲 this.scale()。 
     * @return	abs(this)
     */
    public BigDecimal abs() {
    	// 判斷當前的值是否小於0,小於0,返回相反數,否則返回當前值
        return (signum() < 0 ? negate() : this);
    }
 
    /**
     * 返回其值爲此 BigDecimal 絕對值的 BigDecimal(根據上下文設置進行舍入)。
     * @param mc	要使用的上下文
     * @return	abs(this),必要時進行舍入
     */
    public BigDecimal abs(MathContext mc) {
    	// 判斷當前的值是否小於0,小於0,返回相反數,否則返回當前值
        return (signum() < 0 ? negate(mc) : plus(mc));
    }
 
    /**
     * 返回 BigDecimal,其值爲 (-this),其標度爲 this.scale()。 
     * @return	-this
     */
    public BigDecimal negate() {
        BigDecimal result;
        if (intCompact != INFLATED)// 將-intCompact和scale轉換爲 BigDecimal。
            result = BigDecimal.valueOf(-intCompact, scale);
        else {
        	// 將 BigInteger 的(intVal.negate()的相反數)和 scale轉換爲 BigDecimal。
            result = new BigDecimal(intVal.negate(), scale);
            result.precision = precision;
        }
        return result;
    }
    /**
     * 返回其值爲 (-this) 的 BigDecimal(根據上下文設置進行舍入)。 
     * @param mc	要使用的上下文
     * @return	abs(this),必要時進行舍入
     */
    public BigDecimal negate(MathContext mc) {
        return negate().plus(mc);
    }
 
    /**
     * 返回 BigDecimal,其值爲 (+this),其標度爲 this.scale()。 
     * 此方法僅返回此 BigDecimal,該方法與一元減方法 negate() 對稱。
     * @return	this
     */
    public BigDecimal plus() {
        return this;
    }
 
    /**
     * 返回其值爲 (+this) 的 BigDecimal(根據上下文設置進行舍入)。 
     * 此方法的效果與 round(MathContext) 方法的效果相同。
     * @param mc	要使用的上下文。
     * @return	this,必要時進行舍入。零結果具有的標度爲 0。 
     */
    public BigDecimal plus(MathContext mc) {
        if (mc.precision == 0)                 // 請不要四捨五入
            return this;
        return doRound(this, mc);// 根據mc設置返回一個this的四捨五入的BigDecimal對象
    }
    /**
     * 返回此 BigDecimal 的正負號函數。
     * @return	當此 BigDecimal 的值爲負、零或正時,返回 -1、0 或 1。
     */
    public int signum() {
        return (intCompact != INFLATED)?
            Long.signum(intCompact):
            intVal.signum();
    }
 
    /**
     * 返回此 BigDecimal 的標度。如果爲零或正數,則標度是小數點後的位數。
     * 如果爲負數,則將該數的非標度值乘以 10 的負 scale 次冪。例如,-3 標度是指非標度值乘以 1000。
     * @return	此 BigDecimal 的標度。
     */
    public int scale() {
        return scale;
    }
    /**
     * 返回此 BigDecimal 的精度。(精度是非標度值的數字個數。) 
     * 零值的精度是 1。 
     * @return	此 BigDecimal 的精度
     */
    public int precision() {
        int result = precision;
        if (result == 0) {// 精度爲0
            long s = intCompact;
            if (s != INFLATED)// 以數字表示的s的絕對值的長度
                result = longDigitLength(s);
            else// 返回當前對象的intVal的絕對值的長度
                result = bigDigitLength(inflate());
            precision = result;
        }
        return result;
    }
 
    /**
     * 返回其值爲此 BigDecimal 的非標度值 的 BigInteger。(計算 (this * 10的this.scale()次冪)。) 
     * @return	此 BigDecimal 的非標度值
     */
    public BigInteger unscaledValue() {
        return this.inflate();
    }
 
    // 舍入模式
 
    /*
     * 舍入遠離零的舍入模式。在丟棄非零部分之前始終增加數字。
     * 注意,此舍入模式始終不會減少計算值的大小。 
     */
    public final static int ROUND_UP =           0;
    /*
     * 接近零的舍入模式。在丟棄某部分之前始終不增加數字(即截短)。
     * 注意,此舍入模式始終不會增加計算值的大小。
     */
    public final static int ROUND_DOWN =         1;
 
    /*
     * 接近正無窮大的舍入模式。如果 BigDecimal 爲正,則舍入行爲與 ROUND_UP 相同;
     * 如果爲負,則舍入行爲與 ROUND_DOWN 相同。注意,此舍入模式始終不會減少計算值。
     */
    public final static int ROUND_CEILING =      2;
 
    /*
     * 接近負無窮大的舍入模式。如果 BigDecimal 爲正,則舍入行爲與 ROUND_DOWN 相同;
     * 如果爲負,則舍入行爲與 ROUND_UP 相同。注意,此舍入模式始終不會增加計算值。
     */
    public final static int ROUND_FLOOR =        3;
 
    /*
     * 向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則爲向上舍入的舍入模式。
     * 如果捨棄部分 >= 0.5,則舍入行爲與 ROUND_UP 相同;否則舍入行爲與 ROUND_DOWN 相同。
     * 注意,這是我們大多數人在小學時就學過的舍入模式。 
     */
    public final static int ROUND_HALF_UP =      4;
 
    /*
     * 向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則爲上舍入的舍入模式。
     * 如果捨棄部分 > 0.5,則舍入行爲與 ROUND_UP 相同;否則舍入行爲與 ROUND_DOWN 相同。 
     */
    public final static int ROUND_HALF_DOWN =    5;
 
    /*
     * 向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。
     * 如果捨棄部分左邊的數字爲奇數,則舍入行爲與 ROUND_HALF_UP 相同;
     * 如果爲偶數,則舍入行爲與 ROUND_HALF_DOWN 相同。
     * 注意,在重複進行一系列計算時,此舍入模式可以將累加錯誤減到最小。 
     */
    public final static int ROUND_HALF_EVEN =    6;
 
    /*
     * 斷言請求的操作具有精確的結果,因此不需要舍入。
     * 如果對獲得精確結果的操作指定此舍入模式,則拋出 ArithmeticException。 
     */
    public final static int ROUND_UNNECESSARY =  7;
 
 
    //擴展/舍入操作
 
    /**
     * 返回根據 MathContext 設置進行舍入後的 BigDecimal。如果精度設置爲 0,則不進行任何舍入操作。 
     * 此方法的效果與 plus(MathContext) 方法的效果相同。
     * @param mc	要使用的上下文
     * @return	根據 MathContext 設置舍入後的 BigDecimal
     */
    public BigDecimal round(MathContext mc) {
        return plus(mc);
    }
 
    /**
     * 返回 BigDecimal,其標度爲指定值,其非標度值通過此 BigDecimal 的非標度值乘以或除以十的適當次冪來確定,以維護其總值。
     * 如果該操作減少標度,則非標度值必須被除(而不是乘),並且該值可以更改;在這種情況下,將指定的舍入模式應用到除法中。
     * @param newScale	要返回的 BigDecimal 值的標度
     * @param roundingMode	要應用的舍入模式
     * @return	一個 BigDecimal,其標度爲指定值,其非標度值可以通過此 BigDecimal 的非標度值乘以或除以十的適當次冪來確定,以維護其總值。
     */
    public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
        return setScale(newScale, roundingMode.oldMode);
    }
 
    /**
     * 返回一個 BigDecimal,其標度爲指定值,其非標度值通過此 BigDecimal 的非標度值乘以或除以十的適當次冪來確定,以維護其總值。
     * 如果該操作減少標度,則非標度值必須被除(而不是乘),並且該值可以更改;在這種情況下,將指定的舍入模式應用到除法中。 
     * 注意,由於 BigDecimal 對象是不可變的,此方法的調用不會 導致初始對象被修改,這與使用名爲 setX 變異字段 X 方法的常規約定相反。
     * 相反,setScale 返回具有適當標度的對象;返回的對象不一定是新分配的。 
     * 相對於此遺留方法,應優先使用新的 setScale(int, RoundingMode) 方法。 
     * @param newScale	要返回的 BigDecimal 值的標度
     * @param roundingMode	要應用的舍入模式
     * @return
     */
    public BigDecimal setScale(int newScale, int roundingMode) {
    	// 如果 roundingMode 不表示一個有效的舍入模式
        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
            throw new IllegalArgumentException("Invalid rounding mode");
 
        int oldScale = this.scale;
        if (newScale == oldScale)        // 簡單的情況,標度一致
            return this;
        if (this.signum() == 0)            // 0可以有任何scale
        	// 將 0和 newScale轉換爲 BigDecimal。
            return BigDecimal.valueOf(0, newScale);
 
        long rs = this.intCompact;
        if (newScale > oldScale) {// 新標度大於舊標度
            int raise = checkScale((long)newScale - oldScale);
            BigInteger rb = null;
            // 計算rs * 10 ^ raise;
            if (rs == INFLATED ||
                (rs = longMultiplyPowerTen(rs, raise)) == INFLATED)
                rb = bigMultiplyPowerTen(raise);// 計算this * 10 ^ raise
            return new BigDecimal(rb, rs, newScale,
                                  (precision > 0) ? precision + raise : 0);
        } else {
            // newScale < oldScale -- 減少一些數字
            // 由於四捨五入的影響,無法預測精度(precision)。
            int drop = checkScale((long)oldScale - newScale);
            if (drop < LONG_TEN_POWERS_TABLE.length)
            	// 內部用於除法運算。 
                return divideAndRound(rs, this.intVal,
                                      LONG_TEN_POWERS_TABLE[drop], null,
                                      newScale, roundingMode, newScale);
            else // 內部用於除法運算。 
                return divideAndRound(rs, this.intVal,
                                      INFLATED, bigTenToThe(drop),
                                      newScale, roundingMode, newScale);
        }
    }
 
    /**
     * 返回一個 BigDecimal,其標度爲指定值,其值在數值上等於此 BigDecimal 的值。
     * 如果這不可能,則拋出 ArithmeticException。 
     * 此調用通常用於增加標度,在這種情況下,可以保證存在指定標度和正確值的 BigDecimal。
     * 如果調用方知道 BigDecimal在其小數部分的結尾有足夠多的零(即其整數值中的十的因子),則該調用也可用於減少標度,以允許重新標度,而不更改其值。 
     * 此方法返回與 setScale 的兩個參數版本相同的結果,但是,爲調用方省去了指定舍入模式的麻煩(舍入模式不影響結果)。 
     * 注意,由於 BigDecimal 對象是不可變的,因此此方法的調用不會 導致初始對象被修改,這與使用名爲 setX 變異字段 X 方法的常規約定相反。
     * 相反,setScale 返回具有適當標度的對象;返回的對象不一定是新分配的。 
     * @param newScale	要返回的 BigDecimal 值的標度
     * @return	一個 BigDecimal,其標度爲指定值,其非標度值可以通過此 BigDecimal 的非標度值乘以或除以十的適當次冪來確定,以維護其總值
     */
    public BigDecimal setScale(int newScale) {
        return setScale(newScale, ROUND_UNNECESSARY);
    }
 
    // 小數點移動操作
 
    /**
     * 返回一個 BigDecimal,它等效於將該值的小數點向左移動 n 位。如果 n 爲非負數,則調用僅將 n 添加到該標度。
     * 如果 n 爲負數,則該調用等效於 movePointRight(-n)。
     * 此調用返回的 BigDecimal 的值爲 (this × 10的-n次冪),標度爲 max(this.scale()+n, 0)。 
     * @param n	將小數點向左移動的位數
     * @return	一個 BigDecimal,它等效於將該值的小數點向左移動 n 位
     */
    public BigDecimal movePointLeft(int n) {
        // 如果n==Integer.MIN_VALUE,則不能使用movePointRight(-n)
        int newScale = checkScale((long)scale + n);
        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
    }
 
    /**
     * 返回一個 BigDecimal,它等效於將該值的小數點向右移動 n 位。如果 n 爲非負數,則該調用僅從該標度減去 n。
     * 如果 n 爲負,則該調用等效於 movePointLeft(-n)。
     * 此調用返回的 BigDecimal 的值爲 (this × 10n),標度爲 max(this.scale()-n, 0)。 
     * @param n	將小數點向右移動的位數
     * @return	一個 BigDecimal,它等效於將該值的小數點向右移動 n 位
     */
    public BigDecimal movePointRight(int n) {
        // 如果n==Integer.MIN_VALUE,則不能使用movePointLeft(-n)
        int newScale = checkScale((long)scale - n);
        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
    }
    /**
     * 返回其數值等於 (this * 10的n次冪) 的 BigDecimal。該結果的標度爲 (this.scale() - n)。 
     * @param n
     * @return
     */
    public BigDecimal scaleByPowerOfTen(int n) {
        return new BigDecimal(intVal, intCompact,
                              checkScale((long)scale - n), precision);
    }
 
    /**
     * 返回數值上等於此小數,但從該表示形式移除所有尾部零的 BigDecimal。
     * 例如,從 BigDecimal 值 600.0 中移除尾部零,該值具有的 [BigInteger, scale] 組件等於 [6000, 1],
     * 使用 [BigInteger, scale] 組件生成的 6E2 等於 [6, -2] 
     * @return
     */ince 1.5
     */
    public BigDecimal stripTrailingZeros() {
    	// 如果當前對象的intVal爲空,分配適當的BigInteger給intVal字段,
        this.inflate();
        BigDecimal result = new BigDecimal(intVal, scale);
        // 從當前BigDecimal對象中刪除不重要的後置零,直到不能刪除更多的零爲止。
        result.stripZerosToMatchScale(Long.MIN_VALUE);
        return result;
    }
 
    // 比較運算
    /**
     * 將此 BigDecimal 與指定的 BigDecimal 比較。
     * 根據此方法,值相等但具有不同標度的兩個 BigDecimal 對象(如,2.0 和 2.00)被認爲是相等的。
     * 相對六個 boolean 比較運算符 (<, ==, >, >=, !=, <=) 中每一個運算符的各個方法,優先提供此方法。
     * 建議使用以下語句執行上述比較:(x.compareTo(y) <op> 0),其中 <op> 是六個比較運算符之一。
     * @param val	將此 BigDecimal 與之比較的 BigDecimal。
     * @return 當此 BigDecimal 在數字上小於、等於或大於 val 時,返回 -1、0 或 1。
     */        less than, equal to, or greater than {@code val}.
    public int compareTo(BigDecimal val) {
        // 等比例(scale)和無膨脹的情況的快速路徑。
        if (scale == val.scale) {
            long xs = intCompact;
            long ys = val.intCompact;
            if (xs != INFLATED && ys != INFLATED)
                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
        }
        int xsign = this.signum();// 返回正負號
        int ysign = val.signum();
        if (xsign != ysign)
            return (xsign > ysign) ? 1 : -1;
        if (xsign == 0)
            return 0;
        int cmp = compareMagnitude(val);// 調用內置compareTo()方法
        return (xsign > 0) ? cmp : -cmp;
    }
 
	/**
	 * 忽略符號的compareTo版本
	 * @param val	將此 BigDecimal 與之比較的 BigDecimal。
	 * @return
	 */
    private int compareMagnitude(BigDecimal val) {
        // 匹配scales,避免不必要的膨脹
        long ys = val.intCompact;
        long xs = this.intCompact;
        if (xs == 0)
            return (ys == 0) ? 0 : -1;
        if (ys == 0)
            return 1;
 
        int sdiff = this.scale - val.scale;// 標度之差
        if (sdiff != 0) {// 標度不相同處理
            // Avoid matching scales if the (adjusted) exponents differ
        	// 如果(調整後的)指數(exponents )不同,避免匹配標度(scales)
            int xae = this.precision() - this.scale;   // [-1]
            int yae = val.precision() - val.scale;     // [-1]
            if (xae < yae)
                return -1;
            if (xae > yae)
                return 1;
            BigInteger rb = null;
            if (sdiff < 0) {
            	// 計算xs * 10 ^ -sdiff == INFLATED
                if ( (xs == INFLATED ||
                      (xs = longMultiplyPowerTen(xs, -sdiff)) == INFLATED) &&
                     ys == INFLATED) {
                	// 計算this* 10 ^ -sdiff
                    rb = bigMultiplyPowerTen(-sdiff);
                    return rb.compareMagnitude(val.intVal);
                }
            } else { // sdiff > 0
            	// 計算ys * 10 ^ sdiff == INFLATED
                if ( (ys == INFLATED ||
                      (ys = longMultiplyPowerTen(ys, sdiff)) == INFLATED) &&
                     xs == INFLATED) {
                	// 計算this* 10 ^ sdiff
                    rb = val.bigMultiplyPowerTen(sdiff);
                    return this.intVal.compareMagnitude(rb);
                }
            }
        }
        if (xs != INFLATED)// 標度相同處理
        	// 判斷xs和ys的絕對值的大小
            return (ys != INFLATED) ? longCompareMagnitude(xs, ys) : -1;
        else if (ys != INFLATED)
            return 1;
        else // 將this.intVal的大小數組與指定的val.intVal的大小數組進行比較。
            return this.intVal.compareMagnitude(val.intVal);
    }
    /**
     * 比較此 BigDecimal 與指定的 Object 的相等性。
     * 與 compareTo 不同,僅當兩個 BigDecimal 對象的值和標度都相等時,
     * 此方法才認爲它們相等(因此通過此方法進行比較時,2.0 不等於 2.00)。 
     * 覆蓋:類 Object 中的 equals
     * @param x	將與此 BigDecimal 進行比較的 Object
     * @return	當且僅當指定的 Object 爲 BigDecimal,並且其值和標度都等於此 BigDecimal 的值和標度時,返回 true。
     */
    @Override
    public boolean equals(Object x) {
        if (!(x instanceof BigDecimal))
            return false;
        BigDecimal xDec = (BigDecimal) x;
        if (x == this)
            return true;
        if (scale != xDec.scale)
            return false;
        long s = this.intCompact;
        long xs = xDec.intCompact;
        if (s != INFLATED) {
            if (xs == INFLATED)// 返回給定的xDec.intVal的compact 值,如果太大,則返回INFLATED。
                xs = compactValFor(xDec.intVal);
            return xs == s;
        } else if (xs != INFLATED)// 返回給定的this.intVal的compact 值,如果太大,則返回INFLATED。
            return xs == compactValFor(this.intVal);
 
        return this.inflate().equals(xDec.inflate());
    }
    /**
     * 返回此 BigDecimal 和 val 的最小值。
     * @param val	要計算最小值的值
     * @return	其值爲 BigDecimal 和 val 中較小值的 BigDecimal。根據 compareTo 方法的定義,如果它們相等,則返回 this。
     */
    public BigDecimal min(BigDecimal val) {
        return (compareTo(val) <= 0 ? this : val);
    }
    /**
     * 返回此 BigDecimal 和 val 的最大值
     * @param val	要計算最大值的值
     * @return	其值爲此 BigDecimal 和 val 中較大值的 BigDecimal。根據 compareTo 方法的定義,如果它們相等,則返回 this。
     */
    public BigDecimal max(BigDecimal val) {
        return (compareTo(val) >= 0 ? this : val);
    }
 
    // 哈希函數
 
    /**
     * 返回此 BigDecimal 的哈希碼。
     * 注意,數值上相等但標度不同的兩個 BigDecimal 對象(如,2.0 和 2.00)通常沒有 相同的哈希碼。 
     * 覆蓋:類 Object 中的 hashCode
     * @return	此 BigDecimal 的哈希碼
     */
    @Override
    public int hashCode() {
        if (intCompact != INFLATED) {
            long val2 = (intCompact < 0)? -intCompact : intCompact;
            int temp = (int)( ((int)(val2 >>> 32)) * 31  +
                              (val2 & LONG_MASK));
            return 31*((intCompact < 0) ?-temp:temp) + scale;
        } else
            return 31*intVal.hashCode() + scale;
    }
    // 格式轉換器
 
    /**
     * 回此 BigDecimal 的字符串表示形式,如果需要指數,則使用科學記數法。 
     * 根據以下步驟可創建 BigDecimal 的標準的規範化字符串形式:首先,使用不帶前導零的字符 '0' 至 '9'
     * (如果其值爲零,則使用單個 '0' 字符)將 BigDecimal 的非標度值的絕對值轉換爲以十爲基數的字符串。 
     * 其次,計算調整的指數;這是無效的標度,加上轉換的非標度值中的字符數減 1。
     * 即:-scale+(ulength-1),其中 ulength 是十進制數字中非標度值的絕對值的長度(其精度)。 
     * 如果該標度大於或等於零,並且調整的指數大於或等於 -6,則在不使用指數記數法的情況下將該數轉換爲字符形式。
     * 在這種情況下,如果標度爲零,則不添加小數點,如果標度爲正數,則插入小數點,且標度指定了小數點右邊的字符個數。
     * 必要時,將字符 '0' 添加到轉換的非標度值的左邊。如果插入後小數點前面沒有字符,則以傳統字符 '0' 爲前綴。 
     * 否則(即:如果標度爲負數,或者調整的指數小於 -6),使用指數記數法將該數轉換爲字符形式。
     * 在這種情況下,如果轉換後的 BigInteger 多於一位數,則小數點插入在第一個數字之後。
     * 然後,將字符形式的指數作爲轉換的非標度值(也許具有插入的小數點)的後綴;這包含字母 'E' 和直接跟在其後的轉換爲字符形式的調整指數。
     * 後者的基數爲十,使用的字符是 '0' 到 '9',沒有前導零,並且,如果調整的指數爲負數,
     * 則總是以符號字符 '-' ('\u002D') 爲前綴,否則以 '+' ('\u002B') 爲前綴。 
     * 最後,如果非標度值小於零,則整個字符串以減號 '-' ('\u002D') 爲前綴。如果非標度值爲零或正數,則不使用符號字符作爲前綴。 
     * 示例: 
     * 		對於左邊的每個表示形式 [unscaled value, scale],得到的字符串顯示在右邊。 
     * 			[123,0]      "123"
     * 			[-123,0]     "-123"
     * 			[123,-1]     "1.23E+3"
     * 			[123,-3]     "1.23E+5"
     * 			[123,1]      "12.3"
     * 			[123,5]      "0.00123"
     * 			[123,10]     "1.23E-8"
     * 			[-123,12]    "-1.23E-10"
     *  注: 
     *  1、可區分的 BigDecimal 值和此轉換的結果之間存在一對一的映射關係。
     *  即:每個可區分的 BigDecimal 值(非標度值和標度)都有唯一的字符串表示形式,作爲使用 toString 的結果。
     *  如果使用 BigDecimal(String) 構造方法將該字符串表示形式轉換爲 BigDecimal,則將恢復初始值。 
     *  2、給定的數產生的字符串總是相同的;它不受語言環境的影響。
     *  這意味着它可以用作交換十進制數據的規範化字符串表示形式,或用作 Hashtable 的關鍵字等等。
     *  NumberFormat 類及其子類可以處理區分語言環境的數的格式化和分析。 
     *  3、toEngineeringString() 方法可用於在工程計數法中表示帶有指數的數。
     *  setScale 方法可用於對 BigDecimal 進行舍入,使其小數點後的位數爲已知位數。 
     *  4、使用 Character.forDigit 提供的數字到字符的映射關係。 
     *  覆蓋:類 Object 中的 toString
     *  @return	此 BigDecimal 的字符串表示形式。
     */
    @Override
    public String toString() {
        String sc = stringCache;
        if (sc == null)// 科學記數法
            stringCache = sc = layoutChars(true);
        return sc;
    }
    /**
     * 返回此 BigDecimal 的字符串表示形式,需要指數時,則使用工程計數法。 
     * 返回如 toString() 方法中所描述的表示 BigDecimal 的字符串,不包括使用指數記數法的情況,
     * 將十的冪調整爲三的倍數(工程記數法),這樣,非零值的整數部分的範圍是 1 到 999。
     * 如果對零值使用指數記數法,則使用小數點和小數的一(或二)個零數字,以便保留零值的標度。
     * 注意,與 toString() 的輸出不同,如果使用 string constructor 將輸出字符串轉換爲 BigDecimal,
     * 則此方法的輸出不 保證恢復此 BigDecimal 的相同 [integer, scale] 對。
     * 此方法滿足以下較弱約束,即產生的結果在數值上始終等於將字符串構造方法應用到方法的輸出得到的結果。 
     * @return	此 BigDecimal 的字符串表示形式,如果需要指數,則使用工程記數法
     */
    public String toEngineeringString() {
        return layoutChars(false);// 工程計數法
    }
 
    /**
     * 返回不帶指數字段的此 BigDecimal 的字符串表示形式。
     * 對於具有正標度的值,小數點右邊的數字個數用於指示標度。
     * 對於具有零或負標度的值,生成得到的字符串,好像將該值轉換爲在數值上等於具有零標度的值一樣,並且好像零標度值的所有尾部零都出現在該結果中。
     *  如果非標度值小於零,則整個字符串以減號 '-' ('\u002D') 爲前綴。
     *  如果非標度值爲零或正數,則沒有任何符號字符作爲前綴。 
     *  注意,如果將此方法的結果傳遞到 string constructor,則只需要恢復此 BigDecimal 的數值;
     *  新的 BigDecimal 的表示形式可以有不同的標度。
     *  尤其是,如果此 BigDecimal 具有負標度,則在由字符串構造方法進行處理時,此方法產生的字符串將具有零標度。
     * @return
     */
    public String toPlainString() {
        BigDecimal bd = this;
        if (bd.scale < 0)// 標度小於0
            bd = bd.setScale(0);
        bd.inflate();// 如果bd的intVal爲空,分配適當的BigInteger給intVal字段,
        if (bd.scale == 0)      // 沒有小數點
            return bd.intVal.toString();
        return bd.getValueString(bd.signum(), bd.intVal.abs().toString(), bd.scale);
    }
 
    /**
     * 字符串拼接——私有工具類
     * @param signum	當前BigDecimal的符號
     * @param intString	當前BigDecimal的intVal的絕對值
     * @param scale	當前BigDecimal的標度(小數點)
     * @return
     */
    private String getValueString(int signum, String intString, int scale) {
        /* 插入小數點 */
        StringBuilder buf;
        int insertionPoint = intString.length() - scale;
        if (insertionPoint == 0) {  /* 小數點在intVal之前,例如0.1*/
            return (signum<0 ? "-0." : "0.") + intString;
        } else if (insertionPoint > 0) { /* 小數點在intVal內部,例如111.1111*/
            buf = new StringBuilder(intString);
            buf.insert(insertionPoint, '.');
            if (signum < 0)
                buf.insert(0, '-');
        } else { /* 我們必須在小數點和intVal之間插入0,例如:0.00123*/
            buf = new StringBuilder(3-insertionPoint + intString.length());
            buf.append(signum<0 ? "-0." : "0.");
            for (int i=0; i<-insertionPoint; i++)
                buf.append('0');
            buf.append(intString);
        }
        return buf.toString();
    }
 
   /**
     * 將此 BigDecimal 轉換爲 BigInteger。
     * 此轉換類似於 Java Language Specification 中定義的從 double 到 long 的基本收縮轉換:
     * 將丟棄此 BigDecimal 的小數部分。
     * 注意,此轉換會丟失關於 BigDecimal 值的精度信息。 
     * 要在轉換不準確時(即當丟棄非零小數部分時)拋出異常,請使用 toBigIntegerExact() 方法。
     * @return	轉換爲 BigInteger 的此 BigDecimal。
     */urn this {@code BigDecimal} converted to a {@code BigInteger}.
     */
    public BigInteger toBigInteger() {
        // 強制一個整數,平穩
        return this.setScale(0, ROUND_DOWN).inflate();
    }
    /**
     * 將此 BigDecimal 轉換爲 BigInteger,以檢查丟失的信息。如果此 BigDecimal 具有非零小數部分,則拋出一個異常。
     * @return	轉換爲 BigInteger 的此 BigDecimal。
     */
    public BigInteger toBigIntegerExact() {
        // 四捨五入爲整數,小數部分不爲0的情況除外
        return this.setScale(0, ROUND_UNNECESSARY).inflate();
    }
    /**
     * 將此 BigDecimal 轉換爲 long。
     * 此轉換類似於 Java Language Specification 中定義的從 double 到 short 的基本收縮轉換:
     * 將丟棄此 BigDecimal 的小數部分,並且如果生成的 "BigInteger" 太大而不適合用 long 表示,則僅返回 64 位低位字節。
     * 注意,此轉換會丟失關於此 BigDecimal 值的總大小和精度的信息,並返回帶有相反符號的結果。
     * @return	轉換爲 long 的此 BigDecimal
     */
    public long longValue(){
        return (intCompact != INFLATED && scale == 0) ?
            intCompact:
            toBigInteger().longValue();
    }
 
    /**
     * 將此 BigDecimal 轉換爲 long,以檢查丟失的信息。如果此 BigDecimal 具有非零小數部分,
     * 或者超出 long 結果的可能範圍,則拋出 ArithmeticException。 
     * @return	轉換爲 long 的此 BigDecimal。
     */
    public long longValueExact() {
        if (intCompact != INFLATED && scale == 0)
            return intCompact;
        // 如果整數部分大於19位,則不可能匹配
        if ((precision() - scale) > 19) // [對於負標度也是一樣]
            throw new java.lang.ArithmeticException("Overflow");// 如果 this 具有非零小數部分,或者不適合用 long 表示。
        // Fastpath 0和< 1.0數字(如果非常小,則後者的四捨五入速度非常慢)
        if (this.signum() == 0)
            return 0;
        if ((this.precision() - this.scale) <= 0)
            throw new ArithmeticException("Rounding necessary");
        // 四捨五入爲整數,小數部分不爲0的情況除外
        BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
        if (num.precision() >= 19) // 需要仔細檢查
            LongOverflow.check(num);
        return num.inflate().longValue();
    }
    /**
     * Long值越界問題檢查
     */
    private static class LongOverflow {
        /** BigInteger = Long.MIN_VALUE。 */
        private static final BigInteger LONGMIN = BigInteger.valueOf(Long.MIN_VALUE);
 
        /** BigInteger = Long.MAX_VALUE。 */
        private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE);
        /**
         * 檢查num.intVal的數值範圍
         * @param num
         */
        public static void check(BigDecimal num) {
        	// 如果num的intVal爲空,分配適當的BigInteger給intVal字段,
            num.inflate();
            if ((num.intVal.compareTo(LONGMIN) < 0) ||
                (num.intVal.compareTo(LONGMAX) > 0))
                throw new java.lang.ArithmeticException("Overflow");
        }
    }
 
    /**
     * 將此 BigDecimal 轉換爲 int。
     * 此轉換類似於 Java Language Specification 中定義的從 double 到 short 的基本收縮轉換:
     * 將丟棄此 BigDecimal 的所有小數部分,並且如果生成的 "BigInteger" 太大而不適合用 int 表示,則僅返回 32 位低位字節。
     * 注意,此轉換會丟失關於此 BigDecimal 值的總大小和精度的信息,並返回帶有相反符號的結果。
     * @return	轉換爲 int 的此 BigDecimal
     */
    public int intValue() {
        return  (intCompact != INFLATED && scale == 0) ?
            (int)intCompact :
            toBigInteger().intValue();
    }
	/**
	 * 將此 BigDecimal 轉換爲 int,以檢查丟失的信息。
	 * 如果此 BigDecimal 具有非零小數部分,或者超出 int 結果的可能範圍,則拋出 ArithmeticException。
	 * @return	轉換爲 int 的此 BigDecimal
	 */
    public int intValueExact() {
       long num;
       num = this.longValueExact();     // 將檢查小數部分
       if ((int)num != num)
           throw new java.lang.ArithmeticException("Overflow");
       return (int)num;
    }
 
    /**
     * 將此 BigDecimal 轉換爲 short,以檢查丟失的信息。
     * 如果此 BigDecimal 具有非零小數部分,或者超出 short 結果的可能範圍,則拋出 ArithmeticException。 
     * @return	轉換爲 short 的此 BigDecimal。 
     */
    public short shortValueExact() {
       long num;
       num = this.longValueExact();     // 將檢查小數部分
       if ((short)num != num)
           throw new java.lang.ArithmeticException("Overflow");
       return (short)num;
    }
 
    /**
     * 將此 BigDecimal 轉換爲 byte,以檢查丟失的信息。
     * 如果此 BigDecimal 具有非零小數部分,或者超出 byte 結果的可能範圍,則拋出 ArithmeticException。
     * @return	轉換爲 byte 的此 BigDecimal。
     */
    public byte byteValueExact() {
       long num;
       num = this.longValueExact();     // 將檢查小數部分
       if ((byte)num != num)
           throw new java.lang.ArithmeticException("Overflow");
       return (byte)num;
    }
 
    /**
     * 將此 BigDecimal 轉換爲 float。
     * 此轉換類似於 Java Language Specification 中定義的從 double 到 float 的基本收縮轉換:
     * 如此 BigDecimal 的值太大而不能表示爲 float,
     * 則將其適當地轉換爲 Float.NEGATIVE_INFINITY 或 Float.POSITIVE_INFINITY。
     * 注意,即使在返回值爲有限值的情況下,此轉換也可能丟失關於 BigDecimal 值精度的信息。 
     * @return	
     */
    public float floatValue(){
        if (scale == 0 && intCompact != INFLATED)
                return (float)intCompact;
        // 效率有點低,但肯定能工作。
        return Float.parseFloat(this.toString());
    }
 
    /**
     * 將此 BigDecimal 轉換爲 double。
     * 此轉換類似於 Java Language Specification 中定義的從 double 到 float 的 基本收縮轉換:
     * 如果此 BigDecimal 的數量太大而不能表示爲 double,則將其適當地轉換爲 Double.NEGATIVE_INFINITY 或 Double.POSITIVE_INFINITY。
     * 注意,即使在返回值爲有限值的情況下,此轉換也可能丟失關於 BigDecimal 值精度的信息。
     * @return	類 Number 中的 doubleValue
     */
    public double doubleValue(){
        if (scale == 0 && intCompact != INFLATED)
            return (double)intCompact;
        // 效率有點低,但肯定能工作。
        return Double.parseDouble(this.toString());
    }
 
    /**
     * 返回此 BigDecimal 的 ulp(最後一位的單位)的大小。
     * 非零 BigDecimal 值的 ulp 是此值與下一個具有相同位數的較大 BigDecimal 值之間的正距離。
     * 零值的 ulp 在數值上等於具有 this 標度的 1。
     * 使用與 this 相同的標度存儲該結果,這樣,零和非零值的結果等於 [1, this.scale()]。 
     * @return	this 的 ulp 的大小
     */
    public BigDecimal ulp() {
        return BigDecimal.valueOf(1, this.scale());
    }
 
    /**
     * 爲BigDecimal對象構建字符串表示形式的私有類。
     * StringBuilderHelper是作爲線程本地變量構造的,因此它是線程安全的。
     * StringBuilder字段充當緩衝區來保存BigDecimal的臨時表示。
     * 如果其intCompact字段沒有INFLATED,cmpCharArray將保存BigDecimal的壓縮表示的所有字符(如果是負數,則“-”符號除外)。
     * 它由對toString()及其在特定線程中的變體的所有調用共享。
     */
    static class StringBuilderHelper {
        final StringBuilder sb;    // BigDecimal字符串的佔位符
        final char[] cmpCharArray; // 用於放置intCompact的字符數組
 
        StringBuilderHelper() {
            sb = new StringBuilder();
            // 所有非負的long都可以放入19個字符數組中。
            cmpCharArray = new char[19];
        }
 
        /**
         * 訪問器
         * @return
         */
        StringBuilder getStringBuilder() {
            sb.setLength(0);// 設置sb的長度爲0
            return sb;
        }
        /**
         * 獲取cmpCharArray[]
         * @return
         */
        char[] getCompactCharArray() {
            return cmpCharArray;
        }
 
        /**
         * 將intCompact的字符放置到cmpCharArray中,並將偏移量返回到表示開始的數組中。
         *
         * @param intCompact 放入cmpCharArray數量。
         * @return 到表示開始的數組的偏移量。
         * 注意:intCompact必須大於或等於零。
         */
        int putIntCompact(long intCompact) {
            assert intCompact >= 0;
 
            long q;
            int r;
            // 因爲我們是從最低有效位開始的,所以charPos指向cmpCharArray中的最後一個字符。
            int charPos = cmpCharArray.length;
 
            // 迭代,直到商符合int
            while (intCompact > Integer.MAX_VALUE) {
                q = intCompact / 100;
                r = (int)(intCompact - q * 100);
                intCompact = q;
                cmpCharArray[--charPos] = DIGIT_ONES[r];
                cmpCharArray[--charPos] = DIGIT_TENS[r];
            }
 
            // 當i2 >= 100時
            int q2;
            int i2 = (int)intCompact;
            while (i2 >= 100) {
                q2 = i2 / 100;
                r  = i2 - q2 * 100;
                i2 = q2;
                cmpCharArray[--charPos] = DIGIT_ONES[r];
                cmpCharArray[--charPos] = DIGIT_TENS[r];
            }
 
            cmpCharArray[--charPos] = DIGIT_ONES[i2];
            if (i2 >= 10)// 當i2 >= 10時
                cmpCharArray[--charPos] = DIGIT_TENS[i2];
 
            return charPos;
        }
 
        final static char[] DIGIT_TENS = {
            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
        };
 
        final static char[] DIGIT_ONES = {
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        };
    }
 
    /**
     * 將這個BigDecimal轉化爲char[]數組。
     * @param sci	true:用於科學計數法;false:用於工程計數法
     * @return	具有以下BigDecimal的規範字符串表示形式的字符串
     */
    private String layoutChars(boolean sci) {
        if (scale == 0)                      // 零刻度無關緊要
            return (intCompact != INFLATED) ?
                Long.toString(intCompact):
                intVal.toString();
        // 獲取此線程局部變量的當前線程副本中的值。
        StringBuilderHelper sbHelper = threadLocalStringBuilderHelper.get();
        char[] coeff;
        int offset;  // offset是coeff數組的起始索引
        // 求絕對值的意義
        if (intCompact != INFLATED) {
            // 將intCompact的絕對值的字符放置到sbHelper.cmpCharArray中,並將偏移量返回到表示開始的數組中。
            offset = sbHelper.putIntCompact(Math.abs(intCompact));
            coeff  = sbHelper.getCompactCharArray();// 獲取 sbHelper.cmpCharArray[]
        } else {
            offset = 0;
            coeff  = intVal.abs().toString().toCharArray();
        }
 
        /*
         * 構造一個緩衝區,爲所有情況提供足夠的容量。如果需要E表示法,長度爲:如果是負,則+ 1;
         * 如果需要點,則+1,表示“E+”,則+2,+ 10爲調整指數(exponent)。
         * 如果是負的,可以是+1,加上前導“0.00000”
         */
        StringBuilder buf = sbHelper.getStringBuilder();
        if (signum() < 0)             // 前綴“-”,如果是負數
            buf.append('-');
        int coeffLen = coeff.length - offset;
        long adjusted = -(long)scale + (coeffLen -1);
        if ((scale >= 0) && (adjusted >= -6)) { // 普通的數字
            int pad = scale - coeffLen;         // 填充0的計數
            if (pad >= 0) {                     // 0.xxx form
                buf.append('0');
                buf.append('.');
                for (; pad>0; pad--) {
                    buf.append('0');
                }
                buf.append(coeff, offset, coeffLen);
            } else {                         // xx.xx form
                buf.append(coeff, offset, -pad);
                buf.append('.');
                buf.append(coeff, -pad + offset, scale);
            }
        } else { // 需要E符號
            if (sci) {                       // 科學計數法
                buf.append(coeff[offset]);   // 首位字符
                if (coeffLen > 1) {          // 更多信息
                    buf.append('.');
                    buf.append(coeff, offset + 1, coeffLen - 1);
                }
            } else {                         // 工程計數法
                int sig = (int)(adjusted % 3);
                if (sig < 0)
                    sig += 3;                // [調整爲負數]
                adjusted -= sig;             // 現在是3的倍數
                sig++;
                if (signum() == 0) {
                    switch (sig) {
                    case 1:
                        buf.append('0'); // 指數(exponent)是3的倍數
                        break;
                    case 2:
                        buf.append("0.00");
                        adjusted += 3;
                        break;
                    case 3:
                        buf.append("0.0");
                        adjusted += 3;
                        break;
                    default:
                        throw new AssertionError("Unexpected sig value " + sig);
                    }
                } else if (sig >= coeffLen) {   // 都是整數
                    buf.append(coeff, offset, coeffLen);
                    // 可能還需要一些零
                    for (int i = sig - coeffLen; i > 0; i--)
                        buf.append('0');
                } else {                     // xx.xxE form
                    buf.append(coeff, offset, sig);
                    buf.append('.');
                    buf.append(coeff, offset + sig, coeffLen - sig);
                }
            }
            if (adjusted != 0) {             // [sci不可以是0]
                buf.append('E');
                if (adjusted > 0)            // 正的力符號
                    buf.append('+');
                buf.append(adjusted);
            }
        }
        return buf.toString();
    }
    /**
     * 以BigInteger的形式返回10的n次方。
     * @param n	返回的10的冪(>=0)
     * @return	一個值爲(10的n次方)的BigInteger值
     */
    private static BigInteger bigTenToThe(int n) {
        if (n < 0)
            return BigInteger.ZERO;
 
        if (n < BIG_TEN_POWERS_TABLE_MAX) {
            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
            if (n < pows.length)
                return pows[n];
            else// 擴展BIG_TEN_POWERS_TABLE數組
                return expandBigIntegerTenPowers(n);
        }
        // BigInteger.pow很慢,所以通過從一個字符串構造一個BigInteger來生成10的n次冪(仍然不是很快)
        char tenpow[] = new char[n + 1];
        tenpow[0] = '1';
        for (int i = 1; i <= n; i++)
            tenpow[i] = '0';
        return new BigInteger(tenpow);
    }
    /**
     * 擴展BIG_TEN_POWERS_TABLE數組,至少包含10的n次方。
     * @param n	返回的10次方(> = 0)
     * @return	一個值爲(10的n次冪)的BigDecimal,同時將BIG_TEN_POWERS_TABLE數組擴展到大於n的大小。
     */
    private static BigInteger expandBigIntegerTenPowers(int n) {
        synchronized(BigDecimal.class) {
            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
            int curLen = pows.length;
            // 下面的比較和上面的同步語句是爲了防止多個線程展開同一個數組。
            if (curLen <= n) {
                int newLen = curLen << 1;
                while (newLen <= n)
                    newLen <<= 1;
                pows = Arrays.copyOf(pows, newLen);// 複製數組
                for (int i = curLen; i < newLen; i++)
                	// 獲取pows[i - 1] * BigInteger.TEN
                    pows[i] = pows[i - 1].multiply(BigInteger.TEN);
                // 基於以下事實:
                // 1. pows是一個私有的局部變量;
                // 2. 下面的存儲是一個不穩定的存儲。
                // 新創建的數組元素可以安全地發佈。
                BIG_TEN_POWERS_TABLE = pows;
            }
            return pows[n];
        }
    }
 
    private static final long[] LONG_TEN_POWERS_TABLE = {
        1,                     // 0 / 10^0
        10,                    // 1 / 10^1
        100,                   // 2 / 10^2
        1000,                  // 3 / 10^3
        10000,                 // 4 / 10^4
        100000,                // 5 / 10^5
        1000000,               // 6 / 10^6
        10000000,              // 7 / 10^7
        100000000,             // 8 / 10^8
        1000000000,            // 9 / 10^9
        10000000000L,          // 10 / 10^10
        100000000000L,         // 11 / 10^11
        1000000000000L,        // 12 / 10^12
        10000000000000L,       // 13 / 10^13
        100000000000000L,      // 14 / 10^14
        1000000000000000L,     // 15 / 10^15
        10000000000000000L,    // 16 / 10^16
        100000000000000000L,   // 17 / 10^17
        1000000000000000000L   // 18 / 10^18
    };
 
    private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {BigInteger.ONE,
        BigInteger.valueOf(10),       BigInteger.valueOf(100),
        BigInteger.valueOf(1000),     BigInteger.valueOf(10000),
        BigInteger.valueOf(100000),   BigInteger.valueOf(1000000),
        BigInteger.valueOf(10000000), BigInteger.valueOf(100000000),
        BigInteger.valueOf(1000000000),
        BigInteger.valueOf(10000000000L),
        BigInteger.valueOf(100000000000L),
        BigInteger.valueOf(1000000000000L),
        BigInteger.valueOf(10000000000000L),
        BigInteger.valueOf(100000000000000L),
        BigInteger.valueOf(1000000000000000L),
        BigInteger.valueOf(10000000000000000L),
        BigInteger.valueOf(100000000000000000L),
        BigInteger.valueOf(1000000000000000000L)
    };
 
    private static final int BIG_TEN_POWERS_TABLE_INITLEN =
        BIG_TEN_POWERS_TABLE.length;
    private static final int BIG_TEN_POWERS_TABLE_MAX =
        16 * BIG_TEN_POWERS_TABLE_INITLEN;
 
    private static final long THRESHOLDS_TABLE[] = {
        Long.MAX_VALUE,                     // 0
        Long.MAX_VALUE/10L,                 // 1
        Long.MAX_VALUE/100L,                // 2
        Long.MAX_VALUE/1000L,               // 3
        Long.MAX_VALUE/10000L,              // 4
        Long.MAX_VALUE/100000L,             // 5
        Long.MAX_VALUE/1000000L,            // 6
        Long.MAX_VALUE/10000000L,           // 7
        Long.MAX_VALUE/100000000L,          // 8
        Long.MAX_VALUE/1000000000L,         // 9
        Long.MAX_VALUE/10000000000L,        // 10
        Long.MAX_VALUE/100000000000L,       // 11
        Long.MAX_VALUE/1000000000000L,      // 12
        Long.MAX_VALUE/10000000000000L,     // 13
        Long.MAX_VALUE/100000000000000L,    // 14
        Long.MAX_VALUE/1000000000000000L,   // 15
        Long.MAX_VALUE/10000000000000000L,  // 16
        Long.MAX_VALUE/100000000000000000L, // 17
        Long.MAX_VALUE/1000000000000000000L // 18
    };
 
    /**
     * 計算val * 10 ^ n;
     * 如果可以表示爲long,則返回該產品,否則INFLATED 。
     * @param val
     * @param n
     * @return
     */
    private static long longMultiplyPowerTen(long val, int n) {
        if (val == 0 || n <= 0)
            return val;
        long[] tab = LONG_TEN_POWERS_TABLE;
        long[] bounds = THRESHOLDS_TABLE;
        if (n < tab.length && n < bounds.length) {
            long tenpower = tab[n];
            if (val == 1)
                return tenpower;
            if (Math.abs(val) <= bounds[n])
                return val * tenpower;
        }
        return INFLATED;
    }
 
    /**
     * 計算this* 10 ^ n。
     * Needed mainly to allow special casing to trap zero value
     * @param n
     * @return
     */
    private BigInteger bigMultiplyPowerTen(int n) {
        if (n <= 0)
            return this.inflate();
 
        if (intCompact != INFLATED)
            return bigTenToThe(n).multiply(intCompact);// 10的n次冪*intCompact
        else
            return intVal.multiply(bigTenToThe(n));// intVal*10的n次冪
    }
 
    /**
     * 如果intVal爲空,則爲intVal字段分配適當的BigInteger,即使用緊湊表示。
     * @return
     */
    private BigInteger inflate() {
        if (intVal == null)
            intVal = BigInteger.valueOf(intCompact);
        return intVal;
    }
 
    /**
     * 匹配兩個BigDecimal的比例(scales )以對齊它們的最小有效數字。
     * 如果val[0]和val[1]的標度(scales)不同,則重新標度(無損地)較低的BigDecimal,使它們匹配。
     * 也就是說,較低比例(lower-scaled)的引用將被具有與其他BigDecimal相同比例(scale)的新對象的引用所替代。
     * @param val
     */
    private static void matchScale(BigDecimal[] val) {
        if (val[0].scale == val[1].scale) {
            return;
        } else if (val[0].scale < val[1].scale) {
            val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
        } else if (val[1].scale < val[0].scale) {
            val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
        }
    }
 
    /**
     * 從流中重新構造BigDecimal實例(即反序列化它)。
     * @param s	正在讀取的流。
     * @throws java.io.IOException
     * @throws ClassNotFoundException
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
            // 讀取所有字段
        s.defaultReadObject();
            // 驗證可能錯誤的字段
        if (intVal == null) {
            String message = "BigDecimal: null intVal in stream";
            throw new java.io.StreamCorruptedException(message);
            // [現在允許所有的標度(scale)]
        }// 獲取intVal(BigInteger)的compact值。
        intCompact = compactValFor(intVal);
    }
 
    /**
     * 將此BigDecimal序列化到相關流
     * @param s	要序列化的流。
     * @throws java.io.IOException
     */
   private void writeObject(java.io.ObjectOutputStream s)
       throws java.io.IOException {
    	       // 必須膨脹(inflate )以保持兼容的串行形式。
       this.inflate();
 
    	       // 寫入適當字段
       s.defaultWriteObject();
   }
 
    /**
     * 返回以十進制數字表示的long絕對值的長度。
     * @param x	long值
     * @return	未縮放值(unscaled value)的長度,以十進制數表示。
     */
    private static int longDigitLength(long x) {
        /*
         * 整數log 10 (x)在(1233/4096)*(1 +整數log 2 (x))的1以內。
         * 分數1233/4096近似於log10(2)
         * 因此,我們首先執行log2的一個版本(Long類的一個變體,具有預先檢查和相反的方向),然後根據powers表進行伸縮(scale)和檢查。 
         */
        assert x != INFLATED;
        if (x < 0)
            x = -x;
        if (x < 10)  // 必須篩選0,還是篩選10
            return 1;
        int n = 64; // 不是63,以避免以後需要添加1
        int y = (int)(x >>> 32);
        if (y == 0) { n -= 32; y = (int)x; }
        if (y >>> 16 == 0) { n -= 16; y <<= 16; }
        if (y >>> 24 == 0) { n -=  8; y <<=  8; }
        if (y >>> 28 == 0) { n -=  4; y <<=  4; }
        if (y >>> 30 == 0) { n -=  2; y <<=  2; }
        int r = (((y >>> 31) + n) * 1233) >>> 12;
        long[] tab = LONG_TEN_POWERS_TABLE;
        // 如果r >=長度,必須有最長可能的數字
        return (r >= tab.length || x < tab[r])? r : r+1;
    }
 
    /**
     * 返回一個BigInteger的絕對值的長度,以十進制數字表示。
     * @param b	BigInteger值
     * @return	未縮放值(unscaled value)的長度,以十進制數字表示
     */
    private static int bigDigitLength(BigInteger b) {
        /*
         * 和Long版本的思路一樣,但是我們需要一個更好的log10(2)的近似值。
         * 使用646456993/2 ^ 31最大可能bitLength報道是準確的。
         */
        if (b.signum == 0)
            return 1;
        int r = (int)((((long)b.bitLength() + 1) * 646456993) >>> 31);
        // 滿足約束(10的r次方) < 0
        return b.compareMagnitude(bigTenToThe(r)) < 0? r : r+1;
    }
 
    /**
     * 從這個BigDecimal中刪除不重要的後置零,直到達到首選比例(scale)或不能刪除更多的零爲止。
     * 如果首選比例(preferred scale)小於Integer.MIN_VALUE,所有後面的0都將被刪除。
     * 
     * 警告:此方法應該只在新對象上調用,因爲它會改變值字段。
     * @param preferredScale
     * @return	這個BigDecimal的比例(scale)可能會縮小到接近首選的比例(scale)。
     */
    private BigDecimal stripZerosToMatchScale(long preferredScale) {
        this.inflate();
        BigInteger qr[];                // 商-餘對
     // 滿足約束(10的BigInteger.TEN次方) >= 0 && scale > preferredScale
        while ( intVal.compareMagnitude(BigInteger.TEN) >= 0 &&
                scale > preferredScale) {
            if (intVal.testBit(0))// 計算 ((intVal & (1<<0)) != 0)
                break;                  // 奇數不能以0結尾
            qr = intVal.divideAndRemainder(BigInteger.TEN);
            if (qr[1].signum() != 0)
                break;                 // 非0的剩餘部分
            intVal=qr[0];
            scale = checkScale((long)scale-1);  // 可能會溢出
            if (precision > 0)          // 已知調整精度(precision)
              precision--;
        }
        if (intVal != null)
            intCompact = compactValFor(intVal);// 獲取intVal的compact值。
        return this;
    }
    /**
     * 檢查下溢或下溢的標度(scale)。
     * 如果這個BigDecimal是非零的,則在標度(scale)超出範圍時拋出異常。
     * 如果這是零,就把標度(scale)縮小到右邊的極值(the extreme value),如果這個標度(scale)超出範圍的話。
     * @param val	新標度(scale)
     * @return	驗證標度爲int。
     */
    private int checkScale(long val) {
        int asInt = (int)val;
        if (asInt != val) {
            asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            BigInteger b;
            if (intCompact != 0 &&
                ((b = intVal) == null || b.signum() != 0))// 新的標度(scale)超出範圍,則出現ArithmeticException(溢出或下溢)。
                throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
        }
        return asInt;
    }
    /**
     * 圓的一個操作數;僅當數字>0時使用。不改變this;如果需要舍入,則創建並返回一個新的BigDecimal。
     * @param mc	要使用的上下文
     * @return
     */
    private BigDecimal roundOp(MathContext mc) {
        BigDecimal rounded = doRound(this, mc);// 根據mc設置返回一個this的四捨五入的BigDecimal對象
        return rounded;
    }
 
    /**
     * 根據MathContext設置將這個BigDecimal四捨五入;僅在精度(precision )> 0時使用。
     * @param mc
     */
    private void roundThis(MathContext mc) {
    	// 根據mc設置返回一個this的四捨五入的BigDecimal對象
        BigDecimal rounded = doRound(this, mc);
        if (rounded == this)                 //不是圓的
            return;
        this.intVal     = rounded.intVal;
        this.intCompact = rounded.intCompact;
        this.scale      = rounded.scale;
        this.precision  = rounded.precision;
    }
 
    /**
     * 返回一個BigDecimal,根據MathContext設置四捨五入;
     * 僅當mc.precision > 0時使用。不改變this;
     * 如果需要舍入,則創建並返回一個新的BigDecimal。
     * @param d	
     * @param mc	要使用的上下文
     * @return	根據MathContext設置四捨五入的BigDecimal。可以返回這個,如果不需要四捨五入。
     */
    private static BigDecimal doRound(BigDecimal d, MathContext mc) {
        int mcp = mc.precision;
        int drop;
        // 這可能(很少)迭代999=>1000的情況
        while ((drop = d.precision() - mcp) > 0) {
            int newScale = d.checkScale((long)d.scale - drop);
            int mode = mc.roundingMode.oldMode;
            if (drop < LONG_TEN_POWERS_TABLE.length)// 內部用於除法運算。
                d = divideAndRound(d.intCompact, d.intVal,
                                   LONG_TEN_POWERS_TABLE[drop], null,
                                   newScale, mode, newScale);
            else// 內部用於除法運算。
                d = divideAndRound(d.intCompact, d.intVal,
                                   INFLATED, bigTenToThe(drop),
                                   newScale, mode, newScale);
        }
        return d;
    }
 
    /**
     * 返回給定的BigInteger的壓縮值( the compact value),如果太大,則返回INFLATED。依賴於BigInteger的內部表示。
     * @param b
     * @return
     */
    private static long compactValFor(BigInteger b) {
        int[] m = b.mag;
        int len = m.length;
        if (len == 0)
            return 0;
        int d = m[0];
        if (len > 2 || (len == 2 && d < 0))
            return INFLATED;
 
        long u = (len == 2)?
            (((long) m[1] & LONG_MASK) + (((long)d) << 32)) :
            (((long)d)   & LONG_MASK);
        return (b.signum < 0)? -u : u;
    }
    /**
     *	判斷x和y的絕對值的大小
     * @param x
     * @param y
     * @return	-1:x<y;0:x=y;x>y:1
     */
    private static int longCompareMagnitude(long x, long y) {
        if (x < 0)
            x = -x;
        if (y < 0)
            y = -y;
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
    /**
     * 判斷s強轉爲int的範圍
     * @param s
     * @return
     */
    private static int saturateLong(long s) {
        int i = (int)s;
        return (s == i) ? i : (s < 0 ? Integer.MIN_VALUE : Integer.MAX_VALUE);
    }
    /**
     * 內部打印程序
     * @param name
     * @param bd
     */
    private static void print(String name, BigDecimal bd) {
        System.err.format("%s:\tintCompact %d\tintVal %d\tscale %d\tprecision %d%n",
                          name,
                          bd.intCompact,
                          bd.intVal,
                          bd.scale,
                          bd.precision);
    }
 
    /**
     * 檢查這個BigDecimal的內部不變量。這些不變量包括:
     * 	1、對象必須初始化;intCompact必須不是INFLATED,否則intVal是非空的。這兩個條件都可能成立。
     * 	2、如果intCompact和intVal和set的值都是一致的。
     * 	3、如果精度(precision)非零,則必須具有正確的值。
     * 注意:由於這是一個審計方法,我們不應該更改這個BigDecimal對象的狀態。
     * @return
     */
    private BigDecimal audit() {
        if (intCompact == INFLATED) {
            if (intVal == null) {
                print("audit", this);
                throw new AssertionError("null intVal");
            }
            // 檢查精度(precision)
            if (precision > 0 && precision != bigDigitLength(intVal)) {
                print("audit", this);
                throw new AssertionError("precision mismatch");
            }
        } else {
            if (intVal != null) {
                long val = intVal.longValue();
                if (val != intCompact) {
                    print("audit", this);
                    throw new AssertionError("Inconsistent state, intCompact=" +
                                             intCompact + "\t intVal=" + val);
                }
            }
            // 檢查精度(precision)
            if (precision > 0 && precision != longDigitLength(intCompact)) {
                print("audit", this);
                throw new AssertionError("precision mismatch");
            }
        }
        return this;
    }
}

 

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