Integer.bitCount()解析

方法說明

把int類型轉換成二進制,計算二進制中位==1的個數。當用位來存儲狀態時,方法比較有用

源碼

   public static int bitCount(int i) {
        // HD, Figure 5-2
        i = i - ((i >>> 1) & 0x55555555);
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        i = i + (i >>> 8);
        i = i + (i >>> 16);
        return i & 0x3f;
    }

代碼非常簡單,但理解起來不那麼簡單,下面聽我娓娓道來

  1. 方法的思想非常簡單,我要計算32位中有多少個1,我先做切分,兩個一組,總共分成16組,計算每個兩位中有幾個1,然後把16組加起來,不就得到總的1的個數了嗎?
  2. 先看下兩位時怎麼計算1的個數

找規律

兩位   個數
-----------------------
00       0
01       1
10       1
11       2

發現規律:如果高位是0,則結果和數值本身相同;如果是高位是1,則數值本身-1得到結果

  1. 於是我們得到公式 結果 = 參數 - (參數 >>1 & 01),滿足上面規律
    這也是上面算法的第一行 i = i - ((i >>> 1) & 0x55555555);這樣把數值分成了兩兩一組,並且每組中的數值即是1的個數

  2. 下面把所有組的數值加在一起就可以了,我們又兩兩加在一起。我們把高兩位的右移兩位和低兩位加載一起就即可
    結果 =( 高兩位 >>2 ) & 00 11 + 低兩位 & 0011 , 之所以 & 0011 ,是爲了防止高位污染結果
    即第二行代碼 i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

  3. 現在數值被4個一組分成了8組,想辦法把這8個數值加在一起就OK了

  4. 還是一貫思想,再做聚合,8個一組,即是高4位右移4位和低位相加即可,別忘了把高4位搞掉
    i = (i + (i >>> 4)) & 0x0f0f0f0f;

  5. 接下來再做聚合,16個一組,高位右移8位+低位,現在爲啥不搞掉高位了?我們先記住,這個數值中的高位是無效的

  6. 接下來16位一組分成2組,同理高16位也是無效

  7. 我們之道int類型位==1的最大個數是32位,即是 0000 0000 0000 0000 0000 0000 0010 0000,所以我們最後
    & 11 11111 即可,最大數值纔是6位,所以第7\8步超過8位的數組就不用管了,最後會統一搞掉

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章