Bit manipulation, permutate bits
I am trying to make a loop that loops through all different integers where exactly 10 of the last 40 bits are set high, the rest set low. The reason is that I have a map with 40 different values, and I want to sum all different ways ten of these values can be multiplied. (This is just out of curiosity, so it's really the "bitmanip"-loop that is of interest, not the sum as such.)
If I were to do this with e.g. 2 out of 4 bits, it would be easy to set all manually,
0011 = 3,
0101 = 5,
1001 = 9,
0110 = 6,
1010 = 10,
1100 = 12,
but with 10 out of 40 I can't seem to find a method to generate these effectively. I tried, starting with 1023开发者_运维问答 ( = 1111111111 in binary), finding a good way to manipulate this, but with no success. I've been trying to do this in C++, but it's really the general method(if any) that is of interest. I did some googling, but with little success, if anyone has a good link, that would of course be appreciated too. :)
You can use any standard implementation of a choose/combination algorithm. Basically you want to choose 10 bits, out of 40, that will be set to 1
.
That said, 40 choose 10 is 847,660,528. And that number will be multiplied by however many possible "tail" bits that aren't in the top 40. Presumably the tail bits aren't subject to any rules, so if there are k bits, that would be another 2k factor.
This algorithm, even once you implement it, will be very slow. It may be a good idea to think of a better approach to solve whatever problem you have.
Related questions
- Algorithm to return all combinations of k elements from n
A bit more complicated, but done purely by bit manipulation. Your example:
#define WIDTH 4
#define BITS 2
void printbits(long pattern) {
long bit;
for (bit = 1L << WIDTH - 1; bit; bit >>= 1)
putchar(pattern & bit ? 49 : 48);
putchar('\n');
}
void movebits(pattern, bit) {
long mask = 3L << bit;
while (((pattern ^= mask) & mask) && (mask < 1L << WIDTH)) {
mask <<= 1;
printbits(pattern);
if (bit)
movebits(pattern, bit - 1);
}
}
int main() {
long pattern = (1L << BITS) - 1L, mask;
printbits(pattern);
movebits(pattern, BITS - 1);
}
Your real application:
#define WIDTH 40
#define BITS 10
and, as polygenelubricants says, be prepared to wait for bit :) Of course, you will replace printbits
with something more useful to you...
(Edited for insufficient testing :/ Damn typos...)
You can simply use next_permutation
. Here's a sample to reproduce your 2 out of 4 case (the order varies slightly):
#include <iostream>
#include <algorithm>
using namespace std;
int main () {
int bits[] = {0,0,1,1};
do {
for (int i = 0; i < 4; ++i) cout << bits[i] << " ";
cout << endl;
} while ( next_permutation (bits,bits+4) );
return 0;
}
There is a very non-obvious way to do this efficiently: Gosper's method of finding the next higher integer with the same number of 1
bits, from HAKMEM item 175.
lowest_1_bit = prev_combo & -prev_combo;
tmp = prev_combo + lowest_1_bit;
new_combo = (((prev_combo ^ tmp) >> 2) / lowest_1_bit) | tmp;
- the first line finds the rightmost
1
bit; - the second turns the rightmost run of
1
bits to0
, and the0
just to the left of the run to1
; - the third line replaces the
1
bits that were lost by the second line, at the bottom of the word.
Now (assuming you're using a 64-bit integer type) you can start with 1023 and just apply this repeatedly (until the result exceeds 1<<40
).
It's easier if you rewrite this as a set of nested loops indicating bit positions:
0011 = 0 1
0101 = 0 2
1001 = 0 3
0110 = 1 2
1010 = 1 3
1100 = 2 3
That is to say, the position P1 of the first bit runs from 0 to 3-1, and the position of the second bit P2 runs repeatedly from P1+1 to 3. Turning this into a generic recursive function is left as an exercise.
精彩评论