簡體   English   中英

這個位操作在Java中如何工作?

[英]How does this bit manipulation work in Java?

我正在研究Java如何計算int的位集。
在我的腦海里,我有一些像這樣的簡單(我認為是正確的):

public static int bitCount(int number){  
        final int MASK = 0x1;  
        int count = 0;  

        for(int i = 0; i < 32; i++){  
            if(((number >>> i) & MASK) == MASK){  
                count++;  
            }  
        }  
        return count;  
    }  

相反,我找到了一種方法,我完全不知道在做什么(對我來說似乎很神奇):

 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;  

有人可以幫助理解這是什么以及為什么一個簡單的功能,如我最初想到的那個/可能是壞的?

當然

i = i - ((i >>> 1) & 0x55555555);

5的位模式是0101 (4位),因此掩碼是位模式01的重復16次。 該行計算該數字的每兩位對中的位數。 如果考慮兩位對, (i >>> 1) & 0x1得到低位的高位。 現在,有四種可能的兩位模式

00 ~> 00 - 00 = 00
01 ~> 01 - 00 = 01
10 ~> 10 - 01 = 01
11 ~> 11 - 01 = 10

現在每個兩位對包含原始位置的位數。

i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

接下來,我們計算每個四位組(也稱為半字節)中的位數。 通過屏蔽具有0x3 = 0011(b)的半字節,我們得到半字節的低位兩位的位數,並且(i >>> 2) & 0x3從高位的兩位得到計數。蠶食。 現在添加了這些計數。 由於每個計數最多為2,因此總和最多為4,因此不會留下半字節。

i = (i + (i >>> 4)) & 0x0f0f0f0f;

現在計算每個八位字節中的位數。 每個半字節包含在該位置原始中設置的位數。 向右移動四位將計數從每個位置的高階半字節移動到低階半字節,這些都被添加。 然后我們還將計數從低階半字節移動到相鄰八位字節的高階nets,由& 0x0f0f0f0f屏蔽掉。 由於每個八位位組最多可以設置8位,因此計數不會離開八位位組的低位半字節。

i = i + (i >>> 8);

現在我們添加相鄰八位字節對的計數。

i = i + (i >>> 16);

現在我們在高位兩個八位位組和低位二位數中添加計數總數。

return i & 0x3f;

最后,除了最低階八位字節之外的所有八位字節都被屏蔽掉,因為高階八位字節仍然包含中間計數。

您的簡單實現可能被認為是錯誤的原因是性能。 復雜的bit-hack使用較少的操作而沒有分支,因此速度更快。 然而,這更容易出錯。

計算int (或long )中的設置位的另一種巧妙方法是

public static int bitCount(int n) {
    int count = 0;
    while(n != 0) {
        ++count;
        n = n & (n-1);
    }
    return count;
}

這工作,因為n = n & (n-1)清除最后一組位n和離開一切不變。 如果n的位模式結束

...100...0

n-1的位模式是

...011...1

並且n中最后1位之前的位是相同的。 在Java中,保證也可以用於負數,因為整數溢出具有環繞語義,因此如果n = Integer.MIN_VALUE ,則位模式為100...0並且n - 1變為具有位模式的Integer.MAX_VALUE 011...1

cool方法只能工作,因為計算機的int值有限。 因為你需要在計算之前知道所有需要的掩碼,所以它無法在無限范圍(如BigInteger)中輕松工作(以及其他很酷的位算法)。

無論如何,你可以通過以下方式閱讀它的工作原理: http//graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel

它在本章的底部。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM