我遇到了以下循环:
int i=a;
while (i!=0) {
i = (i-1) & a;
}
它有什么意义?它是否打印a
的所有子集位?
答案 0 :(得分:2)
" 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))