对人口计数算法有所了解

时间:2012-10-01 18:13:30

标签: binary bitwise-operators bit operations representation

我找了一些方法来做popcount(设置位数)。我找到了这个,这里

http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan

unsigned int v; // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for(c = 0; v; c++) 
{
    v &= v - 1; // clear the least significant bit set
}

尝试一些例子,它确实有效。二进制操作/表示的哪些属性使其有效?

你能否暗示一些关于popcount和二进制表示的进一步阅读?

2 个答案:

答案 0 :(得分:4)

你开始时的初始v最初设置了n位。

游戏的要点是在循环的每次迭代中减少1位数。这样,我们可以计算在我们到达n = 0的点之前所需的循环迭代次数,以计算出初始n的值。

请注意,如果n = 0,则v = 0,因此循环将在此时停止。但只要v> 0,我们将至少运行一次循环体。在每次迭代中,我们最终得到一个具有少1位设置的v。

这就是原因。我们需要的第一个属性是v && v == v。现在v是一个位序列(确切的位数取决于您的机器/操作系统),您可以从最重要到最不重要的顺序排序。当您递减v时,我们可以注意以下内容:

  1. 最低有效位,称之为v [k],设置为1将设置为0;
  2. 当您递减v时,所有比v [k]更重要的位将更改。
  3. 因此,ANDing v及其递减将保留所有更重要的位,但将v [k]设置为0.并且根据定义,所有位都不如v [k],即v [ k-1] ... v [0]已经为0,因为v [k]是“最低有效位为1”。因此,在ANDing之后,所有不太重要的位将保持为0.结果是v && (v - 1)包含的设置比v少1位。

答案 1 :(得分:0)

1位减去0位会将该位转换为1并导致从左侧的下一位借位,从而导致减去1那里也是。这会继续向左级联,直到您到达1位,从1减去10。此时减法结束。您已将所有0转换为1直至第一个设置位,并将该位从1转换为0

当您and之前和之后的值时,before在第一位右侧有零,而after在该位有零。由于任何以零为零的值都为零,因此您将原始值保留为零,并将单个位设置为零。