【发布时间】:2016-02-10 13:20:26
【问题描述】:
我有一个 32 位随机值(比如 631)。
0...0000001001110111
每个位都是一个标志。如果可能的话,我想从这些位中返回一个随机标志,O(1) 操作。如何从给定值631 中选择位位置 0、1、2、4、5、6 或 9(或对应的值 1、2、4、16、32、64、512)?最好尽可能少地偏向某些位。
我想出的东西:
- 将值右移随机位数(本例中最多 10 个)
- 查看是否设置了 LSB
- 如果是:得到一个位位置(最后移位的位数);完成
- 如果不是:
- 如果结果值 == 0;重新开始
- 如果结果值 != 0,则返回再次移动随机位
上面不是 O(1),如果我们碰巧只“命中”了 0 位,可能需要多次迭代。
- 具有随机值的掩码(和)
- 重复直到剩下 2 的幂,或者在值为 0 时重新开始。
不幸的是,上面不是 O(1)。
我很确定这一定可以通过某种方式进行一些双向加密/屏蔽/魔术......
编辑:
As CodeCaster suggested;这会给我所有设置的位值:
int myvalue = 631;
var matchingmasks = Enumerable.Range(0, 32)
.Select(i => 1 << i)
.Where(i => (myvalue & i) == i)
.ToArray();
从结果数组中,我可以选择一个随机元素,然后我会从给定值中找到我的“随机”位(标志)。然而,这仍然需要一个(隐藏的,因为 Linq)for 循环、“暴力破解”每个可能的位、为结果数组分配内存等。
【问题讨论】:
-
任何随机生成算法(包括最简单的算法)都会在
O(1)中生成一个随机值 -
@:deleted:我不想要二进制表示;请阅读问题。我想从设置的位中选择一个(一个)位,或者有它的位置(例如第 3 位)或者它的“值”(例如第 3 位的 4)@Kilanny:我不想要一个随机数;我想要一个 given 数字中的随机位。
-
如果你有二进制表示,那么你可以操纵它来获取位或位的位置。如果我理解正确,您有 631 want 作为输入,并且您希望输出为 1, 2, 4 , 16, 32
-
@DonaldJansen:
you could manipulate that to get the bits:是的;问题是如何。 (另外:64 和 512 是您为给定值 631 遗漏的可能输出)。 -
另外:避免说“这不是最快的”的诱惑。最快可能不是你的目标。您可能不愿意花费一千万美元来开发定制硬件以尽快解决这个问题。您的目标是“考虑到我的预算和其他限制,速度足够快”。由于我们既不知道您的性能要求也不知道您的预算,因此我们不知道什么可以满足该目标。
标签: c# algorithm bit-manipulation