计算位数:这条线是如何工作的? n=n&(n-1); [复制]
Posted
技术标签:
【中文标题】计算位数:这条线是如何工作的? n=n&(n-1); [复制]【英文标题】:Counting number of bits: How does this line work ? n=n&(n-1); [duplicate] 【发布时间】:2013-03-12 19:21:54 【问题描述】:我需要解释一下这条特定线路的工作原理。 我知道这个函数计算 1 的位数,但是这条线究竟是如何清除最右边的 1 位的呢?
int f(int n)
int c;
for (c = 0; n != 0; ++c)
n = n & (n - 1);
return c;
有人可以简单地向我解释一下或给出一些“证据”吗?
【问题讨论】:
想想长减法和“借用”。 它会清除最右边的位,因为n - 1
的最右边位永远不会与n
相同。
Kernighan's bit-count trick!
位旋转技巧通常应该使用无符号类型来完成,以防您的机器不使用二进制补码作为有符号类型(或者如果编译器尝试根据标准的知识进行一些巧妙的优化)符号类型不需要二进制补码)。
这个问题询问n = n & (n - 1)
,换句话说n &= (n-1)
。建议的“已回答”问题要求其他内容,如其标题中所述:n & (n-1)
做了什么。前者的目的是去除最右边的 value-1 位,而后者是检查 n 是否是 2 的幂。我可以看到这两个表达式看起来相似并且它们的真值表相同,但是这两个问题,因此答案,无疑是不同的
【参考方案1】:
任何无符号整数“n”都将具有以下最后 k 位数字:1 后跟 (k-1) 个零:100...0 请注意,k 可以为 1,在这种情况下没有零。
(n - 1) 将以这种格式结束:0 后跟 (k-1) 1's: 011...1
n & (n-1) 因此将以“k”个零结尾:100...0 & 011...1 = 000...0
因此 n & (n - 1) 将消除最右边的“1”。每次迭代基本上都会删除最右边的“1”数字,因此您可以计算 1 的数量。
【讨论】:
如果平台使用有符号幅度表示而不是二进制补码,这是否适用于负值?【参考方案2】:我一直在复习位操作并遇到了这个问题。现在(3年后)可能对原始海报没有用,但无论如何我都会回答以提高其他观众的质量。
n & (n-1)
等于 0 是什么意思?
我们应该确保我们知道这一点,因为这是打破循环的唯一方法 (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。现在,@ 987654337@ 不为零,因此我们递增c
并尝试使用n=4
执行相同的过程。正如我们在上面看到的,4 是 2 的指数,因此它将在下一次比较中打破循环。 直到n
等于2的幂。
什么是c
?
每循环只加一,从 0 开始。c
是在数字等于 2 的幂之前被切断的位数。
【讨论】:
以上是关于计算位数:这条线是如何工作的? n=n&(n-1); [复制]的主要内容,如果未能解决你的问题,请参考以下文章