Java源碼解釋之Integer.bitCount


Java中的Integer.bitCount(i)的返回值是i的二進制表示中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;
}

 

源碼解析如下:

public static int bitCount(int i) {
        // HD, Figure 5-2
        /**
         * 每兩位為一個單元,把原來單元中1的個數儲存在原來的單元中
         */
        i = i - ((i >>> 1) & 0x55555555);
        /**
         *0x33333333其實就是二進制……00110011(共32位),因為上面的每兩位代表1的個數,所以下面的這幾行就是要把上面每兩位
         * 的數字加起來,下面的這行代碼可以這樣理解,每4位分為一組,然后4位中的每兩位相加,相加的結果在儲存到這4位二進制數中,
         * i & 0x33333333表示每4位中的低2位,(i >>> 2) & 0x33333333表示每4位中的高2位,然后在相加
         */
        i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
        /**
         * 這個更好理解,i >>> 4表示往右移動了4位,然后在與i相加,相當於每8位一組,然后8位中的高4位與低4位相加儲存在低4位中,
         * 然后這里在與0x0f0f0f0f進行與運算,把高4位完全置為0了,因為0x0f0f0f0f用二進制表示就是00001111000011110000111100001111,
         * 看到這里可能有些困惑,這里為什么要與0x0f0f0f0f進行與運算,因為每8位一組的話,最多也就是8,那么4位數足夠了,高4位就沒有必要了,
         * 如果不置為0有沒有影響,其實如果1的位數極少的話是沒什么影響的,但如果1的位數比較多到后面計算的結果可能就會往前進位,導致結果錯誤,
         * 所以這一步要進行一次與運算,那為什么上面的那行代碼沒有把4位一組中的高兩位置0,這是因為4位一組最多有4個1,而2位二進制數最多表示3,
         * 小於4,所以不能置為0,
         *
         */
        i = (i + (i >>> 4)) & 0x0f0f0f0f;
        /**
         * 和上面類似,每16位分為一組,每組中的高8位和低8位相加,這里的代碼相加的很干凈,因為無論是高8位還是低8位中的前4位在上面一行中
         * 都已經置為0了,這里也可以像上面那樣,加完之后在與0x00ff00ff進行與運算,但其實這里已經沒有必要了,因為int類型為32位,
         * 最多也就32個1,用8位數儲存足夠了,所以不會超過8位,也就不用擔心超過8位在往前進1位的問題了。
         */
        i = i + (i >>> 8);
        /**
         * 和上面類似,就不在詳述
         */
        i = i + (i >>> 16);
        /**
         * 到最后為什么要和0x3f進行與運算,0x3f用二進制表示就是111111,因為上面兩行沒有進行與運算,所以前面的數據都是無效的,
         * 只有最后8位是有效的,而后8位的前兩位不用說肯定為0,因為最多也就32個1,用后面6位數表示就已經足夠了,所以這里與0x3f
         * 進行與運算,來計算出最終1的個數
         */
        return i & 0x3f;
}

i=031bi


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM