1. 程式人生 > >為什麼對2^n取餘可以換成與運算

為什麼對2^n取餘可以換成與運算

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