位與運算與取餘
阿新 • • 發佈:2018-11-28
關於位與運算&與取餘
今天在研究hashmap原始碼的時候,發現其原始碼中在解決Entry分佈時,本來大多數人以為會用index = hash % length,但是原始碼中卻使用了index = hash & (lenth -1)的方式。
/** * The default initial capacity - MUST be a power of two. */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
另外由上述還可以注意到,在原始碼中對於Entry陣列容量的定義中,要求容量必須為2的n次冪(或0),於是就搜尋查詢了一下用意。
原來位與也是可以用來取餘的,但是有一個條件:除數必須是2的n次冪才行。舉例子來說明:
9%8=1 1001 & (1000 - 1) =1001 & 0111 =1 // 1001是9的二進位制表示,1000是8的二進位制表示
其實很明顯了,在二進位制計算中,眾所周知的是,一個數右移1位相當於除以2的商,而恰巧被移除出去的那一位就是除以2得到的餘數,例如:
9 >> 1 =1001 >> 1 =100 | 1 =4 餘 1
而且,不僅是除以2,對於一個數k要除以2的n次方,也就是相當於把k向右移n位,而被移出去的n位即正好是我們要求是餘數。
那麼問題就簡單了,實際上,對於除數是2的n次方的算式,我們只需要得到被除數的低n位就可以了,而正好,對於2的n次方這樣的數,我們將其轉換為二進位制之後,它就是第n+1位為1,其餘低位都為0的數,因此我們將其減1,就得到了第n+1位為0,而其他位都為1的數,用此數與被除數k進行位與運算,就得到了被除數的低n位二進位制數,也即是
k%2n的結果。
總結:
若一個數m滿足: m=2n
那麼k % m = k & (m-1)