我想从0,1,2,3...n
中选择一个随机数,但是我想通过k|0<k<n
与选择x
的乘法来降低选择k - 1
的可能性。所以x = (k - 1) / k
。数量越大,拾取的机会就越小。
作为答案,我想看看下一个方法的实现:
int pickANumber(n,x)
这是针对我正在开发的游戏,我认为这些问题是相关的但不完全一样:
答案 0 :(得分:2)
p1 + p2 + ... + pn = 1
p1 = p2 * x
p2 = p3 * x
...
p_n-1 = pn * x
解决这个问题可以:
p1 + p2 + ... + pn = 1
(p2 * x) + (p3 * x) + ... + (pn * x) + pn = 1
((p3*x) * x) + ((p4*x) * x) + ... + ((p_n-1*x) * x) + pn = 1
....
pn* (x^(n-1) + x^(n-2) + ... +x^1 + x^0) = 1
pn*(1-x^n)/(1-x) = 1
pn = (1-x)/(1-x^n)
这为您提供了设置为pn
的概率,您可以从中计算所有其他p1,p2,... p_n-1的概率
现在,您可以使用&#34;黑盒子&#34; RNG选择带分布的数字,就像你提到的线程中那样。
一种简单的方法是设置辅助阵列:
aux[i] = p1 + p2 + ... + pi
现在,在0
到aux[n]
之间绘制一个均匀分布的随机数,并使用二分搜索(辅助数组排序),得到第一个值,aux
中的匹配值大于你得到的随机统一数字
原始答案,对于减法(在编辑问题之前):
对于n
项,您需要解决等式:
p1 + p2 + ... + pn = 1
p1 = p2 + x
p2 = p3 + x
...
p_n-1 = pn + x
解决这个问题可以:
p1 + p2 + ... + pn = 1
(p2 + x) + (p3 + x) + ... + (pn + x) + pn = 1
((p3+x) + x) + ((p4+x) + x) + ... + ((p_n-1+x) + x) + pn = 1
....
pn* ((n-1)x + (n-2)x + ... +x + 0) = 1
pn* x = n(n-1)/2
pn = n(n-1)/(2x)
这为您提供了设置为pn
的概率,您可以从中计算所有其他p1,p2,... p_n-1的概率
现在,您可以使用&#34;黑盒子&#34; RNG选择带分布的数字,就像你提到的线程中那样。
请注意,这并不能保证您将拥有0<p_i<1
所有i
的解决方案,但您不能保证根据您的要求提供一个解决方案,并且它将取决于{的值{1}}和n
适合。
答案 1 :(得分:1)
编辑这个答案适用于OP原始问题,不同之处在于每个概率应该比前一个概率低一个固定数量。
好吧,让我们看看约束说的是什么。你想要 P(k)= P(k - 1) - x 。所以我们有:
P(0)
P(1)= P(0) - x
P(2)= P(0) - 2x ...
此外, Sum k P(k)= 1 。求和,我们得到:
1 =(n + 1)P(0)-x * n / 2(n + 1),
这为您提供了 x 和 P(0)之间的简单约束。解决另一个问题。
答案 2 :(得分:0)
为此,我将使用Mersenne Twister算法进行Boost提供的均匀分布,然后使用映射函数将随机分布的结果映射到实际的数字选择。
这是一个潜在实现的快速示例,尽管我遗漏了四元方程实现,因为它是众所周知的:
int f_of_xib(int x, int i, int b)
{
return x * i * i / 2 + b * i;
}
int b_of_x(int i, int x)
{
return (r - ( r ) / 2 );
}
int pickANumber(mt19937 gen, int n, int x)
{
// First, determine the range r required where the probability equals i * x
// since probability of each increasing integer is x higher of occuring.
// Let f(i) = r and given f'(i) = x * i then r = ( x * i ^2 ) / 2 + b * i
// where b = ( r - ( x * i ^ 2 ) / 2 ) / i . Since r = x when i = 1 from problem
// definition, this reduces down to b = r - r / 2. therefore to find r_max simply
// plugin x to find b, then plugin n for i, x, and b to get r_max since r_max occurs
// when n == i.
// Find b when
int b = b_of_x(x);
int r_max = f_of_xib(x, n, b);
boost::uniform_int<> range(0, r_max);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> > next(gen, range);
// Now to map random number to desired number, just find the positive value for i
// when r is the return random number which boils down to finding the non-zero root
// when 0 = ( x * i ^ 2 ) / 2 + b * i - r
int random_number = next();
return quadtratic_equation_for_positive_value(1, b, r);
}
int main(int argc, char** argv)
{
mt19937 gen;
gen.seed(time(0));
pickANumber(gen, 10, 1);
system("pause");
}