如何使用随机数生成器给出位(0或1)来模拟公平的26面骰子?我想使用比特流来挑选英文字母的字母,这样任何一个字母出现的几率与任何其他字母的几率相同(我知道真实的单词不是那样的,并且每个字母都有特定的频率分布)信,但这里没关系)。使用二进制0/1决策从集合A-Z中公平选取字母的最佳方法是什么?我可以想出几种方法将位映射到字母上,但对我来说并不是很明显它们不会有偏见。有一种已知的好方法吗?
答案 0 :(得分:7)
如果你将自己局限于有限数量的位并且你的骰子有26个边,那么该方法将始终存在偏差。你必须允许你必须查看可能无限数量的位,以确保它是无偏的。
一个简单的算法是选择0和下一个最大数字2^n - 1
之间的随机数(在本例中为31)。如果您随机选择的数字太大,请将其丢弃并重新输入,直到您获得范围内的数字。
显然,这不是一种最佳算法,因为你“浪费”了一些信息,但对于大多数用途来说它应该足够好了。如果某些2^m
的骰子边数刚好高于m
,则最浪费,例如:33边。在这种情况下,您将不得不在几乎50%的时间内丢弃该值。
答案 1 :(得分:4)
这里的基本答案似乎是正确的 - 如果您的随机数0..32大于25,请重新注册。但是,你可以通过寻找26的倍数来增加一个任意长的结果的赔率,这样可以减少长时间的发生。
32 - 26 = 6
64 - 52 = 12
128 - 78 = 50
......等等。我把一个Python脚本拼凑起来,找出最多32位的最佳可用位数,这些结果得到了这个结果:
2^13 - 26 * 315 = 2
2^14 - 26 * 630 = 4
无论哪种方式,如果你使用13或14位,你有1到2 ^ 12的机会重新滚动。在这种情况下,您的算法将是:
def random_character():
r = 8190
while r >= 8190:
r = rand(13) # assuming rand generates an N bit integer
return chr(r % 26 + ord('a'))
编辑:出于好奇,我将这些几率与一些重要值进行比较,看看13是否真的是最佳数字(假设您可以在相同的时间内生成任意数量的位,1到32位 - 如果你不能,13位看起来最好)。根据我的(通常是困倦的)数学,如果你可以像16那样便宜地得到32位,那就去做吧。否则,赞成13。
2^8 through 2^12: by definition, no better than 1/2^12 odds
2^16: diff is 16, so 1/2^11
2^17: diff is 6, so slightly under 1/2^14
2^18: diff is 12, so slightly under 1/2^12
2^19: diff is 24, so slightly under 1/2^14
2^20: diff is 22, so slightly under 1/2^15
2^21: diff is 18, so slightly under 1/2^16
2^22: diff is 10, so slightly under 1/2^18
2^23: diff is 20, so slightly under 1/2^18
2^24: diff is 14, so slightly under 1/2^20
2^25: diff is 2, so 1/2^24
2^26: diff is 4, so 1/2^24
2^27: diff is 8, so 1/2^24
2^28: diff is 16, so 1/2^24
2^29: diff is 6, so slightly under 1/2^26
2^30: diff is 12, so slightly under 1/2^26
2^31: diff is 24, so slightly under 1/2^26
2^32: diff is 22, so slightly under 1/2^27
答案 2 :(得分:1)
在你的情况下,最简单的方法是抛出5位,这给出了32(0-31)个等概率结果。如果你得到一个超出你的范围(大于25)的值,你再试一次(并再次......)
每个字母在这种情况下抛出的“硬币”(比特)的平均数量为
5 x 32 / 26 = 6.15
(供参考,参见geometric distribution)
答案 3 :(得分:0)
一个简单的实现方法是使用固定数量的位(例如,4个字节来获取整数)来组合随机位以获取十进制或整数值。将结果除以所提供的位数的最大可能值,我认为应该给出一个在0-1范围内均匀分布的小数。 (基本上是一个rand()函数)。然后做26 * rand()
答案 4 :(得分:0)
26是二进制的11010 如果超过26,则生成五位:
或概括它:
生成(在基数2中记录n)+ 1位。如果它们超过n,则返回值mod n,或丢弃&再来一次。