加权随机整数
我想为随机生成的数字指定权重,权重如下所示。
0 | 1 | 2 | 3 | 4 | 5 | 6 ───────────────────────────────────────── X | X | X | X | X | X | X X | X | X | X | X | X | X | X | X | X | X | | X | X | X | X | | | X | X | X | | | | X | X | | | | | X | | | | | |
什么是最有效的方法?
@Kerrek的回答很好。
但如果权重的直方图不是所有小整数,你需要更强大的东西:
将[0..1]除以用权重确定的间隔。 在这里,您需要相对尺寸比为7:6:5:4:3:2:1的线段。 所以一个间隔单位的大小是1 /(7 + 6 + 5 + 4 + 3 + 2 + 1)= 1/28,间隔的大小是7 / 28,6 / 28,… 1 / 28。
这些包括概率分布,因为它们总和为1。
现在找到累积分布:
P x 7/28 => 0 13/28 => 1 18/28 => 2 22/28 => 3 25/28 => 4 27/28 => 5 28/28 => 6
现在在[0..1]中生成一个随机r
数,并通过找到最小的x
使得r <= P(x)
在该表中查找。 这是您想要的随机值。
表查找可以使用二进制搜索来完成,当直方图有许多箱时,这是个好主意。
请注意,您正在有效地构建逆累积密度函数,因此有时将其称为逆变换方法。
如果您的数组很小,只需在以下数组中选择一个统一的随机索引:
int a[] = {0,0,0,0,0,0,0, 1,1,1,1,1,1, 2,2,2,2,2, 3,3,3,3, 4,4,4, 5,5, 6};
如果要在运行时生成分发,请使用std::discrete_distribution
。
为了得到你想要的发行版,首先你基本上把你在那里写的X的数量加起来。 你可以这样做(我的C是超级生锈的,所以把它当作伪代码)
int num_cols = 7; // for your example int max; if (num_cols % 2 == 0) // even { max = (num_cols+1) * (num_cols/2); } else // odd { max = (num_cols+1) * (num_cols/2) + ((num_cols+1)/2); }
然后你需要随机选择一个介于1
和max
之间的整数。
因此,如果您的随机整数是r
则最后一步是找到哪个列包含第r个X.这样的东西应该有效:
for(int i=0;i