假设我们有一个随机生成器函数rand5
,它生成1到5之间的随机数,包括1和5。我已经看到,如果你想使用它来生成1到7之间的随机数,包括在内,你应该重复计算
(5 * (rand5() - 1) + rand5())
生成1到30之间的随机数(包括1和30),并重复此过程,直到生成1到21之间的数字,然后取结果mod.7。
为什么不直接使用这个公式直接计算1到7之间的随机数?
(rand5() + rand5() + rand5()) % 7 + 1
答案 0 :(得分:6)
这是一个更简单,相关的问题。假设您要生成1到8之间的数字(包括1和8),并且您有一对六面骰子。如果你试图通过滚动这对骰子产生这样一个随机数,结果模式为8,然后加一个?会发生什么?也就是说,如果您执行以下操作会发生什么?
int value = (rand6() + rand6()) % 8 + 1;
这将在正确的范围内生成一个随机数,但它不会生成统一。具体来说,在骰子卷上获得不同总数的概率是不均匀的:
2: 1 / 36
3: 2 / 36
4: 3 / 36
5: 4 / 36
6: 5 / 36
7: 6 / 36
8: 5 / 36
9: 4 / 36
10: 3 / 36
11: 2 / 36
12: 1 / 36
获取这些数字,将它们修改为8,添加一个,并将它们分组在一起,得出以下概率,即生成1到8之间的每个数字:
1: 5 / 36 (have to roll 8)
2: 4 / 36 (have to roll 9)
3: 4 / 36 (have to roll 2 or 10)
4: 4 / 36 (have to roll 3 or 11)
5: 4 / 36 (have to roll 4 or 12)
6: 4 / 36 (have to roll 5)
7: 5 / 36 (have to roll 6)
8: 6 / 36 (have to roll 7)
请注意,这些概率并不统一;你比其他任何东西都更有可能得到1分,7分或8分。
这个例子并不完全是你提出的建议,但它的想法是一样的。加上多个均匀随机值并不能在它们的总和范围内给出均匀分布,所以如果你从这种非均匀分布开始并使用mods试图将它压缩到一个较小的范围内,你就会得到在该范围内返回 分布,但不一定是统一。
更复杂的公式 - 顺便说一下,它是一种拒绝采样 - 在某个范围内生成一个均匀随机数(1 - 30)重复此过程,直到它得到1之间的某个值 - 21.然后保证在该范围内产生的值是均匀随机的,并且由于21是7的倍数,因此7的修正保证了1到7之间的均匀随机值。