【问题标题】:How to randomly pick a value based on the position of the bit如何根据位的位置随机选择一个值
【发布时间】:2013-10-14 17:22:39
【问题描述】:

有没有办法根据位的位置来选择一个值。问题陈述是:- 对于 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

但是我需要随机选择这个值,所以我想这样做

1)根据位掩码创建一个数组,因此对于 16 位,该数组将有 16 个唯一值。

2) 现在对数组位置做rand运算,得到数组索引。

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

有没有更好的方法?

【问题讨论】:

  • 当你随机选择一个值时,结果应该是一个恰好位设置的值,还是最多一个位设置的值?
  • 只设置了 1 位,也设置在位掩码中

标签: c arrays random bit-manipulation bitwise-operators


【解决方案1】:

如果我理解正确,您想要一个在掩码中也设置了一个位的数字。

为此,我会创建一个 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 */

【讨论】:

  • 但是那样的话,如果我想把它扩展到64位,那就是一个瓶颈了。
【解决方案2】:

如果目标是在最后设置一个最多一个位的值,则不需要数组。您可以简单地随机生成一个介于 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没关系。)

【讨论】:

  • 好吧,我们的目标是有一种更好的方法在可能值的数组中生成一个随机索引,所以如果我在位掩码中设置了 28 位,那么我可以将这 28 个可能的值放入一个数组,然后我可以随机生成该数组的索引。
【解决方案3】:

你可以这样做:

bitMask = 0x28d2;

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

【讨论】:

  • 这不会返回值,只从掩码中设置 1 位。
【解决方案4】:

如果您想要完全设置一个位,您可以使用重试循环,或类似的方法:(添加适当的定义,并可能为mask == 0 添加一个特殊情况)

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

rand_in_range(a, b) 是一个函数,它返回 [a, b> 范围内的随机数(请注意,rand_in_range 的 99% 的实现都是不正确的虽然在大多数测试中看起来都是正确的,最糟糕的错误)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 2021-10-20
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    相关资源
    最近更新 更多