I have a 32bit random value (say 631
).
0...0000001001110111
Each of these bits is a flag. I would like to return a random flag from these bits in, if at all possible, O(1) operation. How would I select the bit position 0, 1, 2, 4, 5, 6 or 9 (or it's corresponding value 1, 2, 4, 16, 32, 64, 512) from the given value 631
? Preferably with as least possible bias towards some bits.
Things I came up with:
- Shift value right random number of bits (max. 10 in this case)
- See if LSB is set
- If it is: got a bit position (last shifted number of bits); done
- if not:
- If resulting value == 0; start over
- If resulting value != 0, go back to shifting random bits again
Above is not O(1) and possibly need multiple iterations if we happen to only 'hit' the 0 bits.
- Mask (and) with random value
- Repeat until power of 2 is left or start over when value is 0.
Again, above is not O(1) unfortunately.
I'm pretty sure this must be possible with some bithisfting/masking/magic somehow...
Edit:
As CodeCaster suggested; this will give me all set bit values:
int myvalue = 631;
var matchingmasks = Enumerable.Range(0, 32)
.Select(i => 1 << i)
.Where(i => (myvalue & i) == i)
.ToArray();
From the resulting array I can pick a random element and I'll have found my 'random' bit (flag) from the given value. However, this still requires a (hidden, because Linq) for-loop, 'brute-forcing' each possible bit, memory allocations for the resulting array etc.