為什麼對2^n取餘可以換成與運算
阿新 • • 發佈:2018-12-20
Java中HashMap計算雜湊值函式如下:
static final int hash(Object obj) {
int i;
return obj != null ? (i = obj.hashCode()) ^ i >>> 16 : 0;
}
Node anode[];//散列表底層陣列
int j;
if((anode = table) == null || (j = anode.length) == 0)
j = (anode = resize()).length;//散列表例項化後的長度,預設16
Object obj2;
int k;
//計算當前元素的雜湊位置,並判斷當前位置是否為空(是否雜湊衝突)
if((obj2 = anode[k = j - 1 & i]) == null){
anode[k] = newNode(i, obj, obj1, null);
} else {
//解決雜湊衝突
}
在計算雜湊位置時k = j - 1 & i
,理論上是將hash值對散列表長度j
(預設長度16)取模,實際則轉換成了與運算。
抽象成計算式:X % 2ⁿ = X & (2ⁿ - 1)
在做取餘運算時,通常用除法除到除不盡時,得到餘數。 對比進位制轉換中,十進位制數轉換成n進位制數時,也通常用除n取餘法。
例如,十進位制的100,要對8取餘,正常操作是讓100多次除以8,最後得到4,在除8過程中事實上已經將100轉換成8進位制數了(144),可以看到對8取餘的餘數即為8進位制下的個位數。
計算機中以2進位制儲存,因此要將取餘運算轉變到二進位制級別的運算,唯一的條件是:對n取餘,n進位制的每一位能對應二進位制中整數位,即8進制中每一位對應二進位制中3位。
8進位制:144 2進位制:001 100 100
很顯然,我們只要將末三位100單獨取出來即得到對8取餘的餘數。
考慮與運算規則:1&1=1,0&1=0,即對1做與運算結果不變。
由此可得:001 100 100 & 000 000 111 = 000 000 100
0111即為7,2^3-1