有一个已知的Random(0,1)
函数,它是一个统一的随机函数,这意味着,它将给出0或1,概率为50%。实施只调用Random(a, b)
Random(0,1)
我到目前为止,将范围a-b放在基于0的数组中,然后我有索引0,1,2 ... b-a。
然后调用RANDOM(0,1)
b-a次,将结果作为生成的idx求和。并返回元素。
然而,由于书中没有答案,我不知道这种方式是正确的还是最好的。如何证明返回每个元素的概率完全相同且为1/(b-a+1)
?
这样做的正确/更好的方法是什么?
答案 0 :(得分:9)
如果您的RANDOM(0,1)返回0或1,每个概率为0.5,那么您可以生成位,直到您有足够的数字表示二进制数(b-a + 1)。这为您提供了一个稍微过大的随机数:如果失败,您可以测试并重复。像这样(在Python中)。
def rand_pow2(bit_count):
"""Return a random number with the given number of bits."""
result = 0
for i in xrange(bit_count):
result = 2 * result + RANDOM(0, 1)
return result
def random_range(a, b):
"""Return a random integer in the closed interval [a, b]."""
bit_count = math.ceil(math.log2(b - a + 1))
while True:
r = rand_pow2(bit_count)
if a + r <= b:
return a + r
答案 1 :(得分:1)
当你对随机数求和时,结果不再均匀分布 - 它看起来像一个高斯函数。查阅“大数定律”或阅读任何概率书/文章。就像翻转硬币100次一样,极不可能给出100个头。它可能会有近50个头和50个尾巴。
答案 2 :(得分:1)
您倾向于将0
范围从a-b
放到m=a-b
是正确的。但是,你不能按照你的说法去做。 This question确切地询问如何执行此操作,the answer使用唯一因子分解。在基础2
中写下e
,跟踪所需的最大指数,例如m
。然后,找到小于2^e
的{{1}}的最大倍数,将其称为k
。最后,使用e
生成RANDOM(0,1)
个数字,将其作为某个数字2
的基础x
扩展,如果x < k*m
,则返回x
,否则再试一次。该程序看起来像这样(当m <2 ^ 2时的简单情况):
int RANDOM(0,m) {
// find largest power of n needed to write m in base 2
int e=0;
while (m > 2^e) {
++e;
}
// find largest multiple of m less than 2^e
int k=1;
while (k*m < 2^2) {
++k
}
--k; // we went one too far
while (1) {
// generate a random number in base 2
int x = 0;
for (int i=0; i<e; ++i) {
x = x*2 + RANDOM(0,1);
}
// if x isn't too large, return it x modulo m
if (x < m*k)
return (x % m);
}
}
现在,您只需将a
添加到结果中,即可在a
和b
之间获得均匀分布的数字。
答案 3 :(得分:0)
分而治之可以帮助我们使用随机(0,1)生成范围[a,b]中的随机数。这个想法是
工作'C'代码如下。
int random(int a, int b)
{
if(a == b)
return a;
int c = RANDOM(0,1); // Returns 0 or 1 with probability 0.5
int mid = a + (b-a)/2;
if(c == 0)
return random(a, mid);
else
return random(mid + 1, b);
}
答案 4 :(得分:0)
如果您的RNG以相同的概率返回{0, 1}
,您可以轻松创建一个以相同概率返回数字{0, 2^n}
的RNG。
要执行此操作,您只需使用原始RNG n
次,即可获得0010110111
之类的二进制数字。每个数字(从0到2 ^ n)都是相同的。
现在很容易从a
到b
获得RNG,其中b - a = 2^n
。您只需创建一个以前的RNG并向其添加a
。
现在最后一个问题是如果b-a
不是2^n
,您应该怎么做?
好东西,你几乎什么都不做。依靠rejection sampling技术。它告诉你,如果你有一个大集合并且在该集合上有一个RNG并且需要从该集合的子集中选择一个元素,你可以继续从一个更大的集合中选择一个元素并丢弃它们,直到它们存在于你的子集中
所以你要做的就是找b-a
并找到第一个n b-a <= 2^n
。然后使用拒绝采样,直到您选择一个较小的b-a
元素。比你刚添加a
。