負數 | -1 |
0 | 0 |
正數 | 1 |
對於BigInteger 他的數據打開就是這麼一種形式
[ 101....32位....1] [ 110....32個....1] ....N個..... [ 0110....32個....1]
它的真值的計算方法與其餘的二進制序列同樣的
二進制爲 0111 1110 的十進制爲126 相信誰都會計算,BigInteger也是如此的
尤爲是對於BigInteger字符串參數的構造形式
千萬不要覺得就是把字符的編碼或者字符轉換成數字切段存放到int數組中
他存放的都是轉換後的真值
下面會詳細介紹
|
原碼 |
符號位+數值位
符號位爲0 表示正數,符號位爲1 表示負數
數值位就是真值的絕對值
又被稱爲帶符號的絕對值表示
|
反碼 | 正數的反碼爲其原碼 負數的反碼爲其原碼的除符號位外,逐位取反 |
補碼 | 正數的補碼爲其原碼 負數的補碼爲其反碼+1 |
第一步求原碼: 先寫出來她的原碼--->符號位+數值位(絕對值) |
第二步求反碼:
若是是正數 反碼與原碼同樣
若是是負數 反碼爲原碼取反(除符號位外,逐位翻轉)
|
第三步求補碼: 若是是正數 補碼與原碼同樣 若是是負數 補碼爲反碼 + 1 |
第四步擴充: 若是不足數據類型的寬度,將須要填充到指定寬度 符號位擴充,也就是正數補0 負數補1 |
總結 無論什麼形式,第一位始終都是符號位,0 表示正數, 1表示負數 正數原碼/反碼/補碼 全都同樣,知道一種就直接獲得另外的形式 負數若是知道補碼,想要獲得他的原碼,只須要對補碼再一次的求補碼便可 |
BigInteger內部使用int數組表示 普通數值使用每一個數值位上的數字進行表示 |
一個BigInteger有多個int 一個普通數值有多個數字位 |
每一個int可以表示的指定進制的最大值--intRadix 中保存的數據
其實 就是 BigInteger 的基於每一個int做爲一個元素的進制基數
|
digitsPerInt 表示不一樣基數(進制)下一個int 可以表示的數字的長度 ,這個位數其實就是按照多長進行分割組裝
intRadix 就是基數
bitsPerDigit 是用來推算須要多少個int的,也就是int數組的長度
|
public BigInteger(String val, int radix) { java
//定義了兩個變量一個光標,光標記錄着應該要處理的數據索引下標 git
//另外一個numDigits 用來保存須要處理的數字位數 也就是有效長度,好比去掉前導零後的 算法
int cursor = 0, numDigits; 數組
final int len = val.length();//傳遞進來的字符數組的長度 dom
//若是給定的基數,不在合法範圍內,那麼拋出異常,不會默認處理 ide
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) 函數
throw new NumberFormatException("Radix out of range"); 測試
//若是字符串長度爲0 也是一種非法的參數 ui
if (len == 0) this
throw new NumberFormatException("Zero length BigInteger");
// Check for at most one leading sign
int sign = 1;
int index1 = val.lastIndexOf('-');
int index2 = val.lastIndexOf('+');
//符號- + 只能出現一個,並且還必須是第一個位置,不然都不合法
//根據最後一個的索引與0 進行比較,能夠簡便的判斷符號位是否合法
if (index1 >= 0) {
if (index1 != 0 || index2 >= 0) {
throw new NumberFormatException("Illegal embedded sign character");
}
sign = -1;
cursor = 1;
} else if (index2 >= 0) {
if (index2 != 0) {
throw new NumberFormatException("Illegal embedded sign character");
}
cursor = 1;
}
//通過前面的判斷,若是有符號位的話,光標的值更新爲1 也就是後續不處理符號位
//若是此時光標的值等於字符長度,說明沒有有效數字了,將會拋出異常
if (cursor == len)
throw new NumberFormatException("Zero length BigInteger");
// Skip leading zeros and compute number of digits in magnitude
//若是有前導0 ,將會去掉這些,光標的位置也會跟着一塊兒移動
while (cursor < len &&
Character.digit(val.charAt(cursor), radix) == 0) {
cursor++;
}
//跳過了全部的0以後就再也不有有效數據了,說明他就是個0
//哪怕他原來設置的負數的0 將會變爲0 的標記
if (cursor == len) {
signum = 0;
mag = ZERO.mag;
return;
}
//記錄實際須要處理的數據長度以及對符號位使用signum進行記錄
numDigits = len - cursor;
signum = sign;
// Pre-allocate array of expected size. May be too large but can
// never be too small. Typically exact.
//根據前面的公式計算實際須要的二進制位數 numDigits須要處理的數字的長度
//bitsPerDigit 裏面記錄了每一個進制1位數須要的二進制位數,可是放大了1024倍,因此還要除以1024 也就是右移10
//真正的值多是小數個,除以1024以後變成了取整了,而後再加上一,百分百夠用,須要的比特位數保存到numBits
long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
if (numBits + 31 >= (1L << 32)) {
reportOverflow();
}
//numWords 記錄的是實際須要的int類型數據的個數,也就是數組的長度
//右移5位就是除以32 就是計算數組的長度,除法會取整,防止1個不足32位的時候,就會變成0了因此numBits加上31 以後再除以32
int numWords = (int) (numBits + 31) >>> 5;
//此時建立真正的保存數據的int數組了
int[] magnitude = new int[numWords];
// Process first (potentially short) digit group
//numDigits 須要處理的數字的個數
//digitsPerInt 保存的是每個int可以保存的指定數制下的字符長度
//若是有餘數,說明有一個不足最大長度的位數
//若是沒有餘數,那麼每一組都是恰好可以保存的最大長度
int firstGroupLen = numDigits % digitsPerInt[radix];
if (firstGroupLen == 0)
firstGroupLen = digitsPerInt[radix];
//第一組數據存放到數組的最後一個
String group = val.substring(cursor, cursor += firstGroupLen);
magnitude[numWords - 1] = Integer.parseInt(group, radix);
if (magnitude[numWords - 1] < 0)
throw new NumberFormatException("Illegal digit");
// Process remaining digit groups
int superRadix = intRadix[radix];
int groupVal = 0;
while (cursor < len) {
group = val.substring(cursor, cursor += digitsPerInt[radix]);
groupVal = Integer.parseInt(group, radix);
if (groupVal < 0)
throw new NumberFormatException("Illegal digit");
// 這個方法是用來累計計算的,方法內部寫的很複雜
//其實邏輯很簡單,好比一個數字序列1234,求他表示的值是多少
// ( ( (1*10)+2 )*10+3 )*10 +4 = 1234
//這個方法就是用來計算的,只不過每個位置是一個int 低32位當作數值 高32位當作進位
destructiveMulAdd(magnitude, superRadix, groupVal);
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
}
獲取符號位 signum() |
經常使用數學函數 negate() 取負 abs() 絕對值
pow(int) 求冪
gcd(BigInteger) 最大公約數
min(BigInteger) 最小值
max(BigInteger) 最大值
|
四則運算與取整求餘
add(BigInteger) 加法
subtract(BigInteger) 減法
multiply(BigInteger) 乘法
divide(BigInteger) 除法(取整)
remainder(BigInteger) 求餘
divideAndRemainder(BigInteger) 取整和求餘 返回的是一個數組
|
獲取基本類型的值
不一樣於基本數值類型的包裝類,此處並非直接強轉的
若是太大intValue 和 longValue 將分別返回低的32位和64位
longValue 和 doubleValue可能會被轉換爲無窮
intValue()
longValue()
floatValue()
doubleValue()
|
數值類型的準確值
longValueExact()
intValueExact()
shortValueExact()
byteValueExact()
所謂準確就是不會舍入或者轉換,由於他們會進行數據長度的校驗
不然將會拋出異常
好比
|
位操做相關
and(BigInteger) 與
or(BigInteger) 或
not() 非
xor(BigInteger) 異或
andNot(BigInteger) 返回其值爲 (this & ~val) 的 BigInteger 等效於 and(val.not())
shiftLeft(int) 左移
shiftRight(int) 右移
|
計算過程相同
對於整型數a,b來講,取模運算或者求餘運算的方法都是:
求模運算和求餘運算在第一步不一樣:
取餘運算在取c的值時,向0 方向舍入;
而取模運算在計算c的值時,向負無窮方向舍入;
所以,求模時結果的符號與b一致,求餘時結果的符號與a一致
若是a,b都是正整數的話,求模與求餘沒有區別
|
mod(BigInteger)
返回其值爲 (this mod m) 的 BigInteger,取模不一樣於 remainder
BigInteger modPow(BigInteger exponent,BigInteger m)
BigInteger modInverse(BigInteger m)
|
public int bitCount() 返回此 BigInteger 的二進制補碼錶示形式中與符號不一樣的位的數量 特別注意這個方法的含義 不是二進制補碼錶示形式的 1 位的數量,而是與符號不一樣的 |
bitLength 最小的二進制補碼錶示形式的位數,不包括 符號位 對於正 BigInteger,這等於常規二進制表示形式中的位數 就是去掉符號位佔用的長度 |
public String toString(int radix) 轉換爲指定基數
toString()
|
hashCode() |
compareTo(BigInteger)
小於、等於或大於 時,返回 -1,0,或 1
|
是否素數
public boolean isProbablePrime(int certainty)
若是此 BigInteger 可能爲素數,則返回 true,若是它必定爲合數,則返回 false
若是 certainty <= 0,則返回 true
參數:
certainty - 調用方容許的不肯定性的度量
若是該調用返回 true,則此 BigInteger 是素數的機率超出 ( 1 - 1/(2的certainty次方) )
此方法的執行時間與此參數的值是成比例的
返回:
若是此 BigInteger 可能爲素數,則返回 true,若是它必定爲合數,則返回 false
|
public static BigInteger probablePrime(int bitLength,
Random rnd)
返回有多是素數的、具備指定長度的正 BigInteger此方法返回的 BigInteger 是合數的機率不超出 2的-100次方
參數:
bitLength - 返回的 BigInteger 的 bitLength。
rnd - 隨機比特源,用這些隨機比特選擇用來進行質數測試的候選數
|
nextProbablePrime
public BigInteger nextProbablePrime()
返回大於此 BigInteger 的可能爲素數的第一個整數
此方法返回的數是合數的機率不超出 2的-100次方
|
testBit(int) 計算 (this & (1<<n)) != 0
setBit(int) 計算 this | (1<<n)
clearBit(int) 計算 this & ~(1<<n)
flipBit(int) 計算 this ^ (1<<n)
|
getLowestSetBit()
返回此 BigInteger 最右端(最低位)1 比特位的索引
也就是從最右邊開始數找到的第一個1
此字節的右端開始到本字節中最右端 1 之間的 0 比特的位數
若是此 BigInteger 不包含1位,則返回 -1
計算 this==0? -1 : log2(this & -this)
|
public byte[] toByteArray() |
BigInteger 內部使用int數組進行數據保存 一個int包含4個byte BigInteger可使用byte數組構造 也天然可以分解成byte數組進行保存 |