问题
Is there a way to pick a value based on the bit position. The problem statement is:- for a 16 bits position, I can set any bits, say I set 1,4,6,7,11,13 bit so the mask would be:-
Bit Positons 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0
Now I need to randomly pick a value based on this bit mask, where only 1 bit is set, so my possible values could be:-
For selecting 4 :0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
For Selecting 7: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
But I need to select this value randomly, so I though of doing it like this
1)Create an Array based on the bit mask, so for 16 bit , the array would have 16 unique values.
2) Now do the rand operation on the array position to get the array index.
3) Use the value at that array index.
Is there a better way of doing it?
回答1:
If I understand correctly you want a number with exactly one bit set that is also set in the mask.
To do this I'd make a while loop that selects a random value between 0 and 16 until it has found one that is also set in the mask:
uint16_t mask = 0x28d2; /* == 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0 */
int bit = 0;
do{
bit = 1 << (rand() % 16); /* sets one random bit between 1 and 16 */
}while(!(mask & bit));
/* bit has now exactly one bit set that is also set in mask */
回答2:
If the goal is to have a value with at most one bit set at the end, you don't need the array. You can simply randomly generate a value between 0-15, then bitshift 1 left by that value to get the mask that you will use to select the bit, like this:
uint16_t myValue = 0xA5;
int shiftValue = rand() % 16;
uint16_t randomMask = 1u << shiftValue;
uint16_t randomValue = myValue & randomMask;
If you instead need a value with exactly one of the bits set at the end, it gets a little trickier. At that point, you could do more or less what you said and use an array to store the positions of the bits that are set (e.g. [1, 4, 6, 7, 11, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
, using zeroes to indicate when there are no more bits set), then generate a random index into the portion of the array containing valid indices. There are certainly other ways to do it too, but this way seems like one that will be fairly clear to future readers of the code (though I would still comment this somewhat carefully, since bit operations can get confusing fast).
(BTW, there are much better ways of generating random numbers than rand()
, and you should probably use one of those if you need anything approaching real randomness - I just used it here as a convenient shorthand, since the actual RNG doesn't matter.)
回答3:
You can do that in this way:
bitMask = 0x28d2;
randomNum = rand() % 16;
randomBit = (1<<randomNum) & bitMask;
回答4:
If you want exactly one bit set, you could use a re-try loop, or something like this: (add the appropriate definitions and maybe add a special case for mask == 0
)
while (mask)
{
array[i++] = mask & -mask;
mask &= mask - 1;
}
return array[rand_in_range(0, i)];
Where rand_in_range(a, b)
is a function that returns a random number in the range [a, b> (be careful with that, 99% of the implementations of rand_in_range
are incorrect while seeming correct in most tests, the worst kind of bug).
来源:https://stackoverflow.com/questions/19236657/how-to-randomly-pick-a-value-based-on-the-position-of-the-bit