生成具有不同概率的范围内的随机数

时间:2012-11-29 21:53:55

标签: algorithm math random probability

如何在A = 1和B = 10之间生成一个随机数,其中每个数字的概率不同?

示例:数字/概率

1 - 20%

2 - 20%

3 - 10%

4 - 5%

5 - 5%

......等等。

我知道一些硬编码的解决方法,遗憾的是,对于更大的范围没有用,例如A = 1000和B = 100000.

假设我们有

    Rand()

返回随机数R,0< R< 1,任何人都可以用适当的方式发布代码示例吗?在c#/ java / actionscript中可以解决。

6 个答案:

答案 0 :(得分:6)

构建一个包含100个整数的数组,并用20 1,20 2,10 3,5 4,5 5等填充它。然后只需从数组中随机选择一个项目。

int[] numbers = new int[100];
// populate the first 20 with the value '1'
for (int i = 0; i < 20; ++i)
{
    numbers[i] = 1;
}
// populate the rest of the array as desired.

// To get an item:
// Since your Rand() function returns 0 < R < 1
int ix = (int)(Rand() * 100);
int num = numbers[ix];

如果物品数量相当小且精度不太严格,这种方法效果很好。也就是说,如果你想要4.375%7,那么你需要一个更大的阵列。

答案 1 :(得分:5)

Knuth归功于A. J. Walker(电子快报10,8(1974),127-128; ACM Trans.Math Software 3(1977),253-256)。

这个想法是,如果你有总共n个不同颜色的k * n个球,那么就可以将球分配到n个容器中,这样容器就可以了。我包含颜色为i的球,最多包含另一种颜色。证据是通过n的归纳。对于诱导步骤,选择球数最少的颜色。

在您的示例中,n = 10.将概率乘以适当的m,使得它们都是整数。所以,也许m = 100,你有20个颜色0球,20个颜色球,10个球颜色2个,5个球颜色3个等等。所以,k = 10.

现在生成一个维度为n的表格,每个条目都是一个概率(颜色i与另一种颜色的比例)和另一种颜色。

要生成随机球,请生成[0,n]范围内的随机浮点数r。设I是整数部分(r的底面),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)

答案 2 :(得分:2)

假设您有一个函数p(n),可以为您提供所需的随机数概率:

r = rand()  // a random number between 0 and 1
for i in A to B do
    if r < p(i) 
      return i
    r = r - p(i)    
done

更快的方法是创建一个(B - A)* 100元素的数组,并用A到B中的数字填充它,使得数组中每个项目的数量与数组大小的比率为它的概率。然后,您可以生成一个统一的随机数来获取数组的索引,并直接访问该数组以获取随机数。

答案 3 :(得分:1)

根据概率将统一随机结果映射到所需的输出。

,例如:

If `0 <= Round() <= 0.2`: result = 1.
If `0.2 < Round() <= 0.4`: result = 2.
If `0.4 < Round() <= 0.5`: result = 3.
If `0.5 < Round() <= 0.55`: result = 4.
If `0.55 < Round() <= 0.65`: result = 5.
...

答案 4 :(得分:1)

这是Knuth's Algorithm的实现。正如一些答案所讨论的那样 1)创建一个总和频率表 2)生成随机整数 3)圆形天花板功能 4)找到随机数落在其中的“求和”范围,并根据它输出原始数组实体

答案 5 :(得分:0)

逆转换

在概率说话中,累积分布函数F(x)返回任何随机抽取的值(称为X)是&lt; =某个给定值x的概率。例如,如果我在这种情况下做了F(4),我会得到.6。因为您示例中概率的运行总和为{.2, .4, .5, .55, .6, .65, ....}。即随机获得小于或等于4的值的概率是.6。但是,我真正想知道的是累积概率函数的,称之为F_inv。我想知道给定累积概率的x值是多少。我想传入F_inv(.6)并返回4.这就是为什么这被称为逆变换方法。

因此,在逆变换方法中,我们基本上试图找到随机统一(0,1)数下降的累积分布中的区间。这适用于perreal和icepack发布的算法。以下是根据累积分布函数说明它的另一种方法

Generate a random number U
for x in A .. B
   if U <= F(x) then return x 

请注意,如果较小的概率出现在分布的开头,那么将循环从B转到A并检查是否U> = F(x)可能更有效