我需要解释这条特定线路的工作原理 我知道这个函数计算1位的数量,但这条线究竟是如何清除最右边的1位?
int f(int n) {
int c;
for (c = 0; n != 0; ++c)
n = n & (n - 1);
return c;
}
有些人可以简单地向我解释一下或给出一些“证明”吗?
答案 0 :(得分:16)
任何无符号整数'n'将具有以下最后k个数字:一个后跟(k-1)个零:100 ... 0 注意k可以是1,在这种情况下没有零。
(n - 1)将以此格式结束:零后跟(k-1)1:011 ... 1
n&因此,(n-1)将以'k'零结束:100 ... 0& 011 ... 1 = 000 ... 0
因此n& (n - 1)将消除最右边的'1'。每次迭代都会基本上删除最右边的'1'数字,因此你可以计算1的数字。
答案 1 :(得分:3)
我一直在梳理位操作并遇到了这个问题。它现在可能对原版海报(3年后)没用,但我还是要回答其他观众提高质量。
n & (n-1)
等于零是什么意思?
我们应该确保我们知道,因为这是打破循环的唯一方法(n != 0
)。
我们说n=8
。该位的表示将是00001000
。 n-1
(或7)的位表示为00000111
。 &
运算符返回两个参数中设置的位。由于00001000
和00000111
没有设置任何类似的位,因此结果为00000000
(或零)。
您可能已经发现,数字8并非随机选择。这是n
是2的幂的一个例子。所有2的幂(2,4,8,16等)将具有相同的结果。
当你传递的指数不是2的指数时会发生什么?例如,当n=6
时,位表示为00000110
和n-1=5
或00000101
。&
适用于这两个参数,它们只有一个共有4位,现在,n=4
不是零,所以我们增加c
并尝试使用n=4
进行相同的处理。正如我们在上面看到的,4是2的指数,因此它将在下一次比较中打破循环。 它会切断最右边的位,直到n
等于2的幂。
什么是c
?
每个循环只增加一个并从0开始。c
是在数字等于2的幂之前截断的位数。