最早由於做作業,結識了java的BigInrger類。讀着讀着,越來越覺得有趣。后來作業做完,也不忍丟下它,索性把全部代碼研究一遍。
開始的時候,一個上午時間最多讀懂2個方法。但是還是有滋有味的堅持了下來。下面開始一點點剖開它“隱藏”的秘密。
首先要想搞懂兩個問題:BigIngeter類的目的——實現高精度數的存儲和計算。基礎的實現機理——用int型(32位)數組存儲數據。(在代碼的注釋中有詳細說明)
/////////////////////////////////////////////////////////////
BigInteger類中的屬性:{
int signum; 符號位,負數是為-1,零時為0,正數是為1
int[] mag; The magnitude of this BigInteger,大數的值}
首先來分析下構造函數 (構造五部曲:1.檢查是否符合標准 2.去零 3.mag賦值 4.去mag中零 5.符號位賦值)
1. 使用byte(8位)型數組構造BigInteger:
/////////////////////////////////////////////////////////////////////
public BigInteger(byte[] val) {
if (val.length == 0)
throw new NumberFormatException("Zero length BigInteger"); //傳入數組長度為零,報錯
if (val[0] < 0) {
mag = makePositive(val);
signum = -1; //如果數組第一個值為負數,則將數組變正存入mag,signum賦-1
} else {
mag = stripLeadingZeroBytes(val); //如果非負,則可直接去掉前面無效零,再賦給mag
signum = (mag.length == 0 ? 0 : 1);
}
}
下面看一下具體調用的函數
///////////////////////////////////////////////////////////////////////////
private static int[] stripLeadingZeroBytes(byte a[]) {
int byteLength = a.length;
int keep;
// Find first nonzero byte
for (keep=0; keep<a.length && a[keep]==0; keep++) //找到第一個有效位,並用keep記錄下
;
// Allocate new array and copy relevant part of input array
int intLength = ((byteLength - keep) + 3)/4; //計算int[]的長度,byte[1/2/3/4]對應int[1]
int[] result = new int[intLength];
int b = byteLength - 1;
for (int i = intLength-1; i >= 0; i--) {
result[i] = a[b--] & 0xff; //向int[]賦值,&0xff的作用是消除對int前24位的影響
(計算機中使用補碼存儲數據,如果直接將一個第一位為“1”的byte值賦給int,則前24為將為“1”)
int bytesRemaining = b - keep + 1;
int bytesToTransfer = Math.min(3, bytesRemaining);
for (int j=8; j <= 8*bytesToTransfer; j += 8)
result[i] |= ((a[b--] & 0xff) << j); //進行移位,每次移動8位,再進行或運算
}
return result;
}
//////////////////////////////////////////////////////////////
private static int[] makePositive(byte a[]) {