有一种优雅的算法被归因于Knuth提到的A. J. Walker (Electronics Letters 10, 8 (1974), 127-128; ACM Trans. Math Software 3 (1977), 253-256)。
思路是,如果你有n种不同颜色的k * n个球总共,那么可以将球分配到n个容器中,使得第i个容器包含颜色为i的球和至多一种其他颜色的球。证明是通过对n进行归纳进行的。对于归纳步骤,选择具有最少数量的球的颜色。
在您的示例中,n = 10。使用适当的m将概率乘以它们都成为整数。因此,可能m = 100,您有20个0号颜色的球,20个1号颜色的球,10个2号颜色的球,5个3号颜色的球等等。所以,k = 10。
现在生成一个维度为n的表格,每个条目都是概率(颜色i的球与其他颜色球的比率)和其他颜色。
要生成随机球,请在范围[0,n)内生成随机浮点数r。让i为整数部分(r的floor)且x为余数(r-i)。
if (x < table[i].probability) output i
else output table[i].other
该算法的优点是,对于每个随机球,您只进行一次比较。
让我举个例子(与Knuth相同)。
考虑模拟掷一对骰子。
因此,P(2) = 1/36,P(3) = 2/36,P(4) = 3/36,P(5) = 4/36,P(6) = 5/36,P(7) = 6/36,P(8) = 5/36,P(9) = 4/36,P(10) = 3/36,P(11) = 2/36,P(12) = 1/36。
乘以36 * 11得到393个球,其中11个是颜色为2的,22个是颜色为3的,33个是颜色为4的,...,11个是颜色为12的。
我们有k = 393 / 11 = 36。
表[2] = (11/36, 颜色为4)
表[12] = (11/36, 颜色为10)
表[3] = (22/36, 颜色为5)
表[11] = (22/36, 颜色为5)
表[4] = (8/36, 颜色为9)
表[10] = (8/36, 颜色为6)
表[5] = (16/36, 颜色为6)
表[9] = (16/36, 颜色为8)
表[6] = (7/36, 颜色为8)
表[8] = (6/36, 颜色为7)
表[7] = (36/36, 颜色为7)