基础知识
位的命名
二进制位由 0 与 1 组成, 把不同的位分别定义如下:
- 把值为 1 的位称为
set bit
- 值为 0 的称为
unset bit
如下图所示,上面的部分为 set bit
,下面的为 unset bit
按位与操作(&)
按位与操作:bitwise AND operator
两边的 bit 都是 1 返回 1,否则返回 0
按位右移操作(»)
按位右移操作:bitwise Right-shift operator
往右边移动一个比特位,也等同于直接除以 2.操作的结果就是,最右边的比特位被删了。
Brian Kernighan 算法
要理解 Brain 算法,首先要理解 n-1 会发生什么?
假设把一个二进制数的最右边的 set bit 称为 p 点。n-1 会将 p 点及后面所有的位置的比特进行反转,0 变成 1,1 变成 0。
以一个 set bit 不在最后一位为例,40
的二进制表示为 101000
。在进行 n-1
操作后,比特位变成了 100111
.
上面的例子中,p 点及后面的比特位从 1000
变成了 0111
。
有了这个基础后,再执行 n & (n-1)
会发生什么?
n -1 只会改变 p 点及后面的位置,对于 p 点之前的位置是保持不变的。那么在 p 点之前的 比特位执行 n & (n-1),前面的比特位不发生改变。 n 与 n-1 ,在 p 及 p 后面的比特位中是完全相反的,所以这部分的比特位在进行 & 操作后,会全部变成 0。
这也就解释了 n & (n-1) 的作用就是,将 p 点及后面的位置全部清零。 那么,被清理的部分有多少个 1 呢?
根据上面 p 点的定义,p 点就是最右边的 1 个 set bit,所以只有 1 位 1.
那么每次减 1 后,计数器加 1,直到 n 变为 0,是不是就把所有的 1 给数出来了呢!
代码示例
|
|