现在我使用以下代码创建一个带有范围的整数的均匀分布。 (我拿出了播种代码)
int random(int min, int max)
{
static std::mt19937 gen;
std::uniform_int<int> dist(min, max);
return dist(gen);
}
我试图修改它以给出一个有利于最小值的分布的分布,并且几乎从不产生接近最大值。我可以看到所有预先制作的发行版,但它们都不是整数。而且我无法根据任何文档判断哪一个符合我的需求。我最接近的是维基百科上显示的卡方分布,其中k = 2
但我无法弄清楚,基于documentation如何使用整数,更不用说设置k值。
如何设置我的函数以使用适当的非均匀整数分布?
仍在努力选择正确的发行版:以下是std::poisson_distribution<int> dist((max - min) * .1);
从0到20的结果:
还没有完全存在,因为0应该比1更频繁,但它应该有助于下一个人,将会发布更多结果。
我的最终解决方案成为了一系列方法:
int randomDist(int min, int max)
{
static std::mt19937 gen;
std::chi_squared_distribution<double> dist(2);
int x;
do
{
x = (int)(max*dist(gen)/10) + min;
}
while (x > max);
return x;
}
给出结果:
答案 0 :(得分:9)
还有其他整数分布,它们名称中没有int
。他们的班级定义确实有typedef IntType result_type
。
您描述的行为是:
binomial_distribution
(t, p)
这会生成0≤ x ≤ t 范围内的数字,因此您需要将范围转换为min
。平均值位于 t·p ,因此请在0附近选择 p 。
std::binomial_distribution<int> dist(max - min, .1);
return dist(gen) + min;
这产生数字0≤x<0。 ∞,但是大数字的可能性逐渐降低。您可以审查max
以上的任何内容,将其限制在某个范围内。参数λ是平均值。选择它以匹配前面的示例:
std::poisson_distribution<int> dist((max - min) * .1);
int x;
do
x = dist(gen) + min;
while (x > max);
return x;
还产生数字0≤x<0。 ∞,但0是最可能的结果,并且每个后续数字都不太可能。再次选择参数以匹配前一个示例的平均值:
std::geometric_distribution<int> dist(1 / ((max - min) * .1 + 1));
int x;
do
x = dist(gen) + min;
while (x > max);
return x;
您还可以使用任何连续分布生成double
,然后将其四舍五入为int
。
答案 1 :(得分:6)
除了在 @aaz 的答案中说的分布之外,请记住,您还可以使用{{3}将均匀分布转换为您可能想到的任何概率分布函数。 (但实际上只对某些“漂亮”函数可行)或inverse transform sampling(在任何情况下都可以应用,但计算成本很高)。
在我看来,符合您需求的分布将是(负面的)rejection sampling:
幸运的是,它是您可以应用逆变换采样的分布之一,这意味着,从均匀[0,1]分布中获取样本,您可以通过应用公式得到指数分布:
x = - ln(1-p)/lambda
带有p
的是来自均匀分布的随机值,lambda
是指数分布的参数;有关详细信息,请参阅exponential distribution。
获得x
(这将是double
)之后,只需将其投放到int
(或使用以下函数对其进行舍入:
int round(double val)
{
// warning: can give counterintuitive results with negative numbers
return int(val+0.5);
}
)获得你的结果。
<强> 修改 强>
顺便说一下,我没有注意到即使是指数分布已经包含在<random>
(here)中......好吧,甚至更好,你不需要编写代码,但是一点点的理论永远不会浪费:)
。