我得到一个函数rand5(),它在均匀分布中生成闭区间[1,5]中的随机整数。我如何使用rand5(),而不是别的,来创建一个函数rand7(),它在[1,7]中生成整数(再次,均匀分布)?
答案 0 :(得分:7)
请注意,使用有限数量的draw5()
调用无法实现完美的统一分布,因为对于每个k
:5^k % 7 != 0
- 所以您将永远有一些“备用”元素。
这是一个解决方案,其中无限数量的draw5()
使用:
画两个数字,x1,x2。这有5 * 5 = 25种可能的结果。
注意25 / 7~ = 3.57。选择3 * 7 = 21种组合,这样每个组合将被映射到[1,7]中的一个数字,对于所有其他4个数字 - 重绘。
例如:
(1,1),(1,2),(2,1) : 1
(3,1),(1,3),(3,2): 2
(3,3),(1,4),(4,1): 3
(2,4),(4,2)(3,4): 4
(4,3), (4,4), (1,5): 5
(5,1), (2,5), (5,2) : 6
(5,3), (3,5), (4,5) : 7
(5,4),(5,5),(2,3), (2,2) : redraw
答案 1 :(得分:4)
这是一个简单的方法:
答案 2 :(得分:2)
rand2() {
if(rand5() > 2.5) return 1
else return 0
}
现在多次使用rand2做一棵树来获得rand7。例如,如果你开始rand7可以在[1,2,3,4,5,6,7]抛出rand2之后给出0你现在是[1,2,3,4]的子集并且在另一次抛出或之后rand2是1,你是[3,4]的子集,最后一次抛出给rand7的输出为4.一般来说,这个树技巧可以用来获取rand2并映射到randx,其中x是任意整数。
答案 3 :(得分:2)
这里有一个元技巧,它可以解决许多这些问题:当我们以某种方式对待这些术语时会产生偏见,所以如果我们在每一步都对它们进行相同的处理,并且仅在<强>设置,我们将远离麻烦。
我们必须至少调用一次rand5()(显然!),但是如果我们分支就会发生坏事,除非我们很聪明。因此,让我们为7种可能性中的每一种调用一次:
In [126]: import random
In [127]: def r5():
.....: return random.randint(1, 5)
.....:
In [128]: [r5() for i in range(7)]
Out[128]: [3, 1, 3, 4, 1, 1, 2]
显然,这些术语中的每一个都同样可能是这些数字中的任何一个......但是其中只有一个碰巧是2,所以如果我们的规则是“选择任何一个术语rand5()返回2”那么它会有工作。或4,或者其他什么,如果我们只是循环足够长的话就会发生。所以有很多方法可以找到有用的东西。这里(伪代码 - 这是可怕的Python)是一种方式:
import random, collections
def r5():
return random.randint(1, 5)
def r7():
left = range(1, 8)
while True:
if len(left) == 1:
return left[0]
rs = [r5() for n in left]
m = max(rs)
how_many_at_max = rs.count(m)
if how_many_at_max == len(rs):
# all the same: try again
continue
elif how_many_at_max == 1:
# hooray!
return left[rs.index(m)]
# keep only the non-maximals
left = [l for l,r in zip(left, rs) if r != m]
给出了
In [189]: collections.Counter(r7() for _ in xrange(10**6))
Out[189]: Counter({7: 143570, 5: 143206, 4: 142827, 2: 142673, 6: 142604, 1: 142573, 3: 142547})