比特掩蔽技术

时间:2017-07-29 18:43:41

标签: algorithm bit-manipulation

我遇到了以下循环:

int i=a;
while (i!=0) {
  i = (i-1) & a;
}

它有什么意义?它是否打印a的所有子集位?

3 个答案:

答案 0 :(得分:2)

and-with-value-minus-one

的含义

" anding的值为减去1"用于剥离最低设置位:

1101110000000101000         # value
               ^---- bottomost set bit   
1101110000000100111         # value minus one
                  ^-- set to one
                 ^--- set to one
                ^---- set to one
               ^----- reset to zero

逐个减法步骤将零到零,并将其下面的所有位设置为1。

随后的&操作然后将新归零的位应用回a。零值右侧的位保持不变(并且一个位置保持不变)。

整体模式

循环将最底部的位置为零并且"恢复"该位右侧的所有位。所以, OP是正确的推测函数循环"所有子集位 a "。

换句话说,代码正在生成每个位的cartesian product被设置和取消设置。因此,迭代次数将是2的幂。

实施例

例如,从二进制为a = 37的{​​{1}}开始,我们得到8个元素序列:00100101

位值为[37, 36, 33, 32, 5, 4, 1, 0],二进制为[32, 4, 1]

序列只是产品的总和。这是一个简短的Python示例:

[00100000, 00000100, 00000001]

答案 1 :(得分:1)

两个例子' a'设置了三位。

a=i(0)=10101,   a=i(0) = 11010
  i(1)=10100,     i(1) = 11000
  i(2)=10001,     i(2) = 10010
  i(3)=10000,     i(3) = 10000
  i(4)=00101,     i(4) = 01010
  i(5)=00100,     i(5) = 01000
  i(6)=00001,     i(6) = 00010
  i(7)=00000,     i(7) = 00000

实际上,此功能从' a'倒数使用与 a 中的非零位一样多的位的任何计数器,使用尽可能多的步骤。这些比特被交织到 a 中的比特位置,这可能具有一些实际的应用,例如:到莫顿数,或生成位于预定位的序列。

退化情况是 a ,所有位都向右移位(1,3,7,15,...),其中循环只是转换为while(i--);

答案 2 :(得分:0)

该算法将计算使用0到(n-1)位设置a的位的所有可能子集,其中n是总位数。第二个规则是,如果a中的位位置为零,则它不会是该子集的一部分。

例如a = 0b111(n = 3)

i = (i-1) & a (i-1 = 110 (6) a = 111 (7) result 110 (6))
i = (i-1) & a (i-1 = 101 (5) a = 111 (7) result 101 (5))
i = (i-1) & a (i-1 = 100 (4) a = 111 (7) result 100 (4))
i = (i-1) & a (i-1 = 011 (3) a = 111 (7) result 011 (3))
i = (i-1) & a (i-1 = 010 (2) a = 111 (7) result 010 (2))
i = (i-1) & a (i-1 = 001 (1) a = 111 (7) result 001 (1))
i = (i-1) & a (i-1 = 000 (0) a = 111 (7) result 000 (0))

这里你可以看到设置a(0b111 = 3位设置)与0,1或2位设置的所有组合。

对于第二条规则,请查看:

i = (i-1) & a (i-1 = 101 (5) a = 110 (6) result 100 (4))
i = (i-1) & a (i-1 = 011 (3) a = 110 (6) result 010 (2))
i = (i-1) & a (i-1 = 001 (1) a = 110 (6) result 000 (0))