Bit hack生成给定数量的1的所有整数

Bit hack生成给定数量的1的所有整数,bit,combinatorics,Bit,Combinatorics,我忘记了用给定的1生成所有整数的技巧。有人记得吗(可能也能解释一下)?关于比特黑客,我想参考以下页面: 关于您的具体问题,请阅读标题为的部分 按字典顺序计算下一位排列 假设我们在一个整数中有一个N位的模式设置为1,并且我们想要在词典编纂的意义上下一个N位的排列。例如,如果N为3且位模式为00010011,则下一个模式将为0000101、00010110、0001100100011010、00011100、00100011,依此类推。下面是计算下一个置换的快速方法 unsigned int v;

我忘记了用给定的1生成所有整数的技巧。有人记得吗(可能也能解释一下)?

关于比特黑客,我想参考以下页面:

关于您的具体问题,请阅读标题为的部分


按字典顺序计算下一位排列

假设我们在一个整数中有一个N位的模式设置为1,并且我们想要在词典编纂的意义上下一个N位的排列。例如,如果N为3且位模式为00010011,则下一个模式将为0000101、00010110、0001100100011010、00011100、00100011,依此类推。下面是计算下一个置换的快速方法

unsigned int v; // current permutation of bits 
unsigned int w; // next permutation of bits

unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1
// Next set to 1 the most significant bit to change, 
// set to 0 the least significant ones, and add the necessary 1 bits.
w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));  
x86 CPU内部的_u内置ctz(v)GNU C编译器返回尾随零的数量。如果您使用的是针对x86的Microsoft编译器,则其内在特性是_BitScanForward。它们都发出bsf指令,但其他体系结构也可以使用等效指令。如果不是,那么考虑使用一种计算前面提到的连续零位的方法。 这是另一个版本,由于它的除法运算符,速度较慢,但它不需要计算尾随的零

unsigned int t = (v | (v - 1)) + 1;  
w = t | ((((t & -t) / (v & -v)) >> 1) - 1);  
感谢阿根廷的Dario Sneidermanis,他于2009年11月28日提供了此信息。

来自

更新测试程序

#包括
#包括
#包括
使用I=uint8\u t;
自动转储(iv){return std::bitset(v);}
我咬了你一口,玩弄你一把(I v){
I t=v |(v-1);//t将v的最低有效0位设置为1
//下一步将要更改的最高有效位设置为1,
//将最低有效位设置为0,并添加必要的1位。
I w=(t+1)|(((~t&-~t)-1)>>(uuu内置ctz(v)+1));
返回w;
}
int main(){
I p=0b001001;

std::cout添加到@sehe的答案中,包括以下内容(最初来自Dario Sneidermanis,也位于。)

如果这是目的,也许值得一提

if (t == (I)(-1)) { return v >> __builtin_ctz(v); }
因此,通过一个额外的小简化

I bit_twiddle_permute2(I v) {
    I t = (v | (v - 1)) + 1;
    if (t == 0) { return v >> __builtin_ctz(v); }
    I w = t | ((~t & v) >> (__builtin_ctz(v) + 1));
    return w;
}

int main() {
    I p = 0b1;
    cout <<  dump(p) << "\n";
    for (I n = bit_twiddle_permute2(p); n>p; n = bit_twiddle_permute2(n)) {
        cout << dump(n) << "\n";
    }
}
I bit\u twidle\u permute2(I-v){
it=(v |(v-1))+1;
如果(t==0){return v>>uu builtin_ctz(v);}
I w=t |((~t&v)>>(uu内置ctz(v)+1));
返回w;
}
int main(){
I p=0b1;

我们为什么不只用
w=v+(v&-v)
?@ptentialunrlsd因为它做的事情不同:@sehe,噢!明白了!非常感谢:)
for (I n = bit_twiddle_permute(p); n>p; n = bit_twiddle_permute(n)) 
if (t == (I)(-1)) { return v >> __builtin_ctz(v); }
I bit_twiddle_permute2(I v) {
    I t = (v | (v - 1)) + 1;
    if (t == 0) { return v >> __builtin_ctz(v); }
    I w = t | ((~t & v) >> (__builtin_ctz(v) + 1));
    return w;
}

int main() {
    I p = 0b1;
    cout <<  dump(p) << "\n";
    for (I n = bit_twiddle_permute2(p); n>p; n = bit_twiddle_permute2(n)) {
        cout << dump(n) << "\n";
    }
}
I bit_twiddle_permute3(I v) {
    int n = __builtin_ctz(v);
    I s = v >> n;  
    I t = s + 1;  
    I w = (t << n) | ((~t & s) >> 1);
    return w;
}
I bit_twiddle_permute3(I v) {
    int n = __builtin_ctz(v);
    I s = v >> n;  
    I t = s + 1;  
    if (v == 0 || t << n == 0) { return s; }
    I w = (t << n) | ((~t & s) >> 1);
    return w;
}