介绍AddressSet.enumerateBits方法的实现,主要是x & (-x)的意义。
1. 基本定义
enumerateBits的意思就是用于枚举比特,或者说罗列比特,即把mask中为1的比特罗列出来。
2. 验证
enumerateBits方法功能比较简单独立,可以直接拿出来执行进行验证。
执行结果如下:
3. x == 0
没有为1的比特,返回空。
4. x != 0
使用x & (-x)取出x中最低的1位,然后把这一位置0后,递归调用helper接着取下一位。
返回的结果是这些比特组成的序列。
5. x & (-x)
结果是取出x中最低的为1的位。
1) -x
-x是对x求相反数,求相反数的操作方法就是取反加一。
2) x取反
x的所有位取反。x & (~x) = 0。
3) 加一:0 + 1 = 1
根据上面表格,如果x原位为1的话,x & (-x)相应的位为1。
因为没有进位,所以更高的位相与的结果都为0。
4) 加一:1 + 1 = (进1)0
根据上面表格,如果x原位为0的话,x & (-x)相应的位为0。
并且产生了一个进位,这个进位的1接着与下一个高位相加。
5) 加一:递进
虽然最开始加一是从最低位开始的,但加1的动作直接忽略x中原值为0的位,逐位加到最低的为1的位而停止。
6. bitIndexes
相似功能使用软件思维的另一种实现是bitIndexes方法:
其返回的是位序。
执行结果如下:
7. 附录
def enumerateBits(mask: BigInt): Seq[BigInt] = {
def helper(x: BigInt): Seq[BigInt] = {
if (x == 0) {
Nil
} else {
val bit = x & (-x)
bit +: helper(x & ~bit)
}
}
helper(mask)
}