给出一个数字' n'和相应的二进制值。我想生成n的所有组合,只使用' n'中设置的位。
例如:如果n = 11且其二进制表示为1011,则组合为:
00000
00001
01000
01001
10000
10001
11000
11001
示例2:如果n = 49且其二进制表示为11001,则组合为:
Runpath Search Paths = @executable_path/Frameworks
最简单的方法是编写一个C子程序来生成这些组合,但是,我需要一些有效的方法/算法来生成这些组合(一些类似于non-standard implementation的位操作技术)。
感谢。
答案 0 :(得分:5)
这是一个使用简单比特琐事的技术的例证。它使用无符号值的二进制算术的保证语义。
在下面的i = n & (i - n)
表达式中,所有子表达式i
,n
,(i - n)
和n & (i - n)
都是相同类型,{{1并且不受整数提升规则的影响。在数学上,子表达式unsigned int
以2 m 为模,其中2 m - 1是可由{{1}表示的最大值}。
(i - n)
示例步骤
假设unsigned int
为49或0000000000110001 2,且当前值#include <stdio.h>
int main(void)
{
unsigned int n = 49;
unsigned int i;
for (i = 0; ; i = n & (i - n)) {
printf("%u", i);
if (i == n)
break;
putchar(' ');
}
putchar('\n');
return 0;
}
为16或0000000000010000 2。然后对于16位,2的补码算法,我们有:
n
这与众所周知的技术相似,即将无符号值i
中的最低“1”位设置为0000000000010000₂
0000000000110001₂ -
----------------
1111111111011111₂
0000000000110001₂ &
----------------
0000000000010001₂ (= 17)
,这是有效的,因为对带有两个补码的数字进行AND运算只会留下结果中设置了最低的'1'位。
答案 1 :(得分:0)
答案 2 :(得分:0)
只通过某些允许的位来迭代整数?这个功能怎么样:
int NextMasked (int val, int mask) {
return ((val | ~mask) + 1) & mask;
}
功能一步一步:
val
并将所有位设置为1,这些位未在mask
mask
return
转到来电。让我们用您的示例(mask = 11
和最初val = 0
)对此进行测试:
Here all values are in binary:
val = 0000, mask = 1011, ~mask = 0100 (bits inverted)
(old) (new)
val |~mask +1 &mask
0000 0100 0101 0001
0001 0101 0110 0010
0010 0110 0111 0011
0011 0111 1000 1000
1000 1100 1101 1001
1001 1101 1110 1010
1010 1110 1111 1011
1011 1111 10000 00000 <-- zeroed, you know it ended
因为这很有趣,让我们测试你的另一个例子(mask = 49
):
Here all values are in binary:
val = 00000, mask = 11001, ~mask = 00110 (bits inverted)
(old) (new)
val |~mask +1 &mask
00000 00110 00111 00001
00001 00111 01000 01000
01000 01110 01111 01001
01001 01111 10000 10000
10000 10110 10111 10001
10001 10111 11000 11000
11000 11110 11111 11001
11001 11111 100000 000000 <-- again, wrapped around (zeroed)
已经很晚了,我实际上没有在电脑上测试过。但这应该有效,或者提出想法......