Expand a random range from 1–5 to 1–7
int i;
do
{
i = 5 * (rand5() - 1) + rand5(); // i is now uniformly random between 1 and 25
} while(i > 21);
// i is now uniformly random between 1 and 21
return i % 7 + 1; // result is now uniformly random between 1 and 7
为什么我不能放
i = 6*(rand5()-1);
有?为什么我们需要“*”和“+”操作
答案 0 :(得分:4)
(rand5() - 1)返回0到4之间的数字。如果将这些数字中的任何一个乘以6,您将只得到5个数字中的一个(0,6,12,18或24)。
以另一种方式执行此操作可确保输出中出现1到21之间的所有可能整数(概率均匀)。
修改强>
5 *(rand5() - 1)会给你一个(0,5,10,15,20)。然后我们在1到5之间添加另一个随机整数,从而填补空白。我们现在有一个1到25之间的随机整数,具有统一的概率。由于我们需要1到21的范围,我们拒绝超过21的任何内容并重试。
答案 1 :(得分:1)
关键是rand5()是 random ,原始表达式中的每个调用都会返回不同的答案。这就是rand5() + rand5()
与2*rand5()
不同的原因。
同样:5 * (rand5() - 1) + rand5()
为5*rand5() + rand5() - 5
,但与6*rand5() - 5
不同,因为每次调用rand5()都会产生不同的结果。
答案 2 :(得分:0)
这是python中的一个例程,它具有统一性的经验测试。
首先是1:5范围内的随机生成器:
>>> def r5(): return randrange(5) + 1
>>> bins = dict((i, 0) for i in range(9))
>>> pp(bins)
{0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0}
>>> for i in range(999999): bins[r5()] += 1
>>> pp(bins)
{0: 0, 1: 199752, 2: 200378, 3: 200452, 4: 199580, 5: 199837, 6: 0, 7: 0, 8: 0}
注意值为1..5的bin计数。
使用的算法是,如果按顺序生成两个r5()数,那么它们是5 * 5 = 25种可能的排列,它们都具有相同的发生可能性。如果我们采用这些排列的任何常数21,我们可以看出我们生成的perm是否在21中,并将每三个值转换为七个整数中的一个返回。如果我们生成一个不在21中的排列,那么我们需要再获得两个r5()值并重复。
r7的代码取决于我为速度做全局的一些常量:
>>> list5 = [1,2,3,4,5]
>>> perm21 = [(x,y) for x in list5 for y in list5 ][:21]
>>> set21 = set(perm21)
>>> def r7():
r = (6,6)
while r not in set21:
r = (r5(), r5())
return (perm21.index(r) // 3) + 1
>>> bins = dict((i, 0) for i in range(9))
>>> for i in range(999999): bins[r7()] += 1
>>> pp(bins)
{0: 0,
1: 142857,
2: 143558,
3: 143046,
4: 142699,
5: 142786,
6: 142439,
7: 142614,
8: 0}
>>>
让我们试着看看10次试验的传播:
>>> bins = dict((i, 0) for i in range(9))
>>> for i in range(9999999): bins[r7()] += 1
>>> pp(bins)
{0: 0,
1: 1429821,
2: 1429851,
3: 1427350,
4: 1428478,
5: 1425243,
6: 1429618,
7: 1429638,
8: 0}
对我来说没问题: - )