2013-10-07 113 views
0

有没有一种方法可以根据位的位置来选择一个值。这个问题的说法是: - 一个16位的位置,我可以设置任何位,说我设定1,4,6,7,11,13位 所以口罩是: -如何根据位的位置随机选择一个值

Bit Positons 0 0 1 0 1 0 0 0 1 1 0 1 0 0 1 0 

现在我需要根据此位掩码随机选择一个值,其中只设置1位,所以我可能的值可能为: -

对于选择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

但我需要选择此值兰特omly,所以我虽然这样做是这样的

1)创建一个基于位掩码的数组,所以对于16位,该数组将有16个唯一值。

2)现在对数组位置进行rand操作以获取数组索引。

3)使用该数组索引处的值。

有没有更好的方法呢?

+1

如果您已经随机挑选了一个值,结果应该是_exactly_一位设置的值还是_at most_一位设置的值? –

+0

正好设置了1位,该位也设置在位掩码 – Viks

回答

3

如果我理解正确,你需要一个只有一个位集的数字,它也在掩码中设置。

要做到这一点,我会做一个while循环,直到它找到一个同样的面具设置选择0到16之间的任意值:如果你想正是一个

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 */ 
+0

但是在这种情况下,如果我想将它扩展到64位,这将是一个瓶颈。 – Viks

0

你可以这样做,以这种方式:

bitMask = 0x28d2; 

randomNum = rand() % 16; 
randomBit = (1<<randomNum) & bitMask; 
+0

这将不会返回值,只有1位从掩码设置。 – Viks

1

如果目标是有一个价值至多一个位设定在结束时,你不需要阵列。你可以简单地随机生成0-15之间的值,则位位移1通过该值留下来获取你将用它来选择位掩码,就像这样:

uint16_t myValue = 0xA5; 
int shiftValue = rand() % 16; 
uint16_t randomMask = 1u << shiftValue; 
uint16_t randomValue = myValue & randomMask; 

如果您不是需要准确的值其中一个位设置在最后,它会变得有点棘手。在这一点上,你可以做更多或更少你说的内容,并使用一个数组来存储所设置的位的位置(例如,[1, 4, 6, 7, 11, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],使用零来指示何时没有更多位被设置),然后生成一个随机索引到数组中包含有效索引的部分。当然也有其他方法可以做到这一点,但这种方式似乎对未来的代码读者来说是相当清楚的(尽管我还是会对此进行仔细的评论,因为位操作可能会让人感到困惑)。

(顺便说一句,还有比rand()产生随机数的更好的方法,你可能应该使用这些,如果你需要任何接近真正随机性的一个 - 我只是用在这里作为一个方便的速记,因为实际RNG没有按没关系。)

+0

那么,目标是有一个更好的方法来生成可能值的数组中的随机索引,所以如果我有28位设置位掩码,那么我可以把这28个可能的值在一个数组中,然后我可以随机生成该数组的索引。 – Viks

0

位设置,你可以使用一个重试循环,或者是这样的:(添加适当的定义,也许增加一个特殊的情况下mask == 0

while (mask) 
{ 
    array[i++] = mask & -mask; 
    mask &= mask - 1; 
} 
return array[rand_in_range(0, i)]; 

哪里rand_in_range(a, b)是返回一个随机函数(请注意,rand_in_range的99%实施不正确,而在大多数测试中看来正确,这是最糟糕的一种错误)。