按概率生成随机数

问题
给定一个概率列表:[0.05, 0.15, 0.2, 0.6],要求生成的随机数符合该列表的概率分布。


---------------------------------------------------------------------------------------------------------------------------------------

在C/C++中,产生一个随机数,可以用下列方法:

点击(此处)折叠或打开

  1. #include >
  2. #include >
  3. #include >
  4. #include >
  5. using namespace std;
  6. int main(void)
  7. {
  8.     srand((unsigned)time(NULL));        // 用来设置rand()产生随机数时的随机数种子,参数必须是整数,如果每次参数都是一致的,rand()产生的随机数每次都是会一样
  9.     for(int i=0; i < 1000; i++)
  10.     {
  11.         count << rand() << '\t';        // 产生0至RAND_MAX间的随机数,RAND_MAX 大小视数据类型而定。
  12.     }
  13.     count << endl;
  14.     
  15.     return 0;
  16. }
  17. ////////////////////////////////////////////////
  18. // 产生一定范围随机数的通用表示公式:
  19. // 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
  20. // 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
  21. // 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;
  22. // 要取得(a,b)的随机整数,使用(rand() % (b-a-1))+ a + 1;
  23. // 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。
  24. // 要取得a到b之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。 
  25. // 要取得0~1之间的浮点数,可以使用rand() / double(RAND_MAX)。 
     

rand() 产生的随机数,并不是真的的随机数,而是伪随机数,是根据一个数(种子)为基准以某个递推公式推算出来的结果,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数。
其内部是使用线性同余法做的,因其周期长,在一定范围内,可以视为随机的。

我们可以产生0~1的随机数,将0~1分成是个数(0.1,0.2,0.3,...,1),每个数的出现的概率是相等的。
将0~1看做一个轮盘,将轮盘按给定的比例划分区域,0.05表示红色,0.15表示蓝色,0.2表示黄色,0.6表示绿色。轮盘中,红色的面积只有轮盘总面积的5%,蓝色的占15%,黄色占20%,绿色占60%。
设置一个指针指向轮盘,转动轮盘,指针最终停留在哪一块颜色的概率,一定是符合给定的概率分布的。
实现代码如下:

点击(此处)折叠或打开

  1. # -*- encoding: utf-8 -*-
  2. import sys, os
  3. import time
  4. import random
  5.     
  6. def solution_one():
  7.     
  8.     property = [0.05, 0.15, 0.2, 0.6]
  9.     selections = {red:0, blue:0, yellow:0, green:0}
  10.     standard = 1.0        # 一个基准
  11.     
  12.     for i in range(10000):
  13.         NotAccept = True
  14.         while(NotAccept):
  15.             selectIndex = int(random.random() * len(property))                # 随机选择一个颜色
  16.             if(random.random() <= (property[selectIndex] / standard)):        # 根据颜色所占比例随机选择
  17.                 NotAccept = False                                             # 选中
  18.         
  19.         selections[selectIndex] += 1
  20.     
  21.     for color,count in selections.item():
  22.         print('color %s count : %d' % (color, count))
  23.     
  24.     
  25. def solution_two():
  26.     
  27.     property = [0.05, 0.15, 0.2, 0.6]
  28.     selections = {red:0, blue:0, yellow:0, green:0}
  29.     sum_property = 0
  30.     rand = random.random()
  31.     
  32.     for i in property:
  33.         sum_property += i
  34.     
  35.     for rount in 1000:                                    # 1000轮迭代测试
  36.         rand = random.random() * sum_property             # 获取随机数
  37.         for index in selections:
  38.             rand -= property[index]                        # 判断一轮迭代中,四个颜色(在此题中中被选中的是哪几个颜色
  39.             if(rand <= 0):
  40.                 selections[index] += 1                     # 选中的颜色加1
  41.     
  42.     
  43.     for color,count in selections.item():
  44.         print('color %s count : %d' % (color, count))
  45.     
  46.     
  47. def solution_three():
  48.     property = [0.05, 0.15, 0.2, 0.6]
  49.     selections = {red:0, blue:0, yellow:0, green:0}
  50.     sum_property = 0
  51.     factor = 0
  52.     rand = random.random()
  53.     
  54.     for i in property:
  55.         sum_prtoperty += i

  56.     for rount in 1000:                                      # 迭代次数
  57.         rand = random.random() * sum_property               # 获取随机数
  58.         for index in selections:
  59.             factor += property[index]                       # 判断一轮迭代中,四个颜色(在此题中)中被选中的是哪几个颜色
  60.             if(rand <= factor):
  61.                 selections[index] += 1                      # 选中的颜色加1
  62.     
  63.     for color,count in selections.item():
  64.         print('color %s count : %d' % (color, count))
  65.     

扩展:
该问题可以归纳为通过均匀分布随机数,生成指定概率分布的随机数问题。类似的问题还有:
1、通过均匀分布随机数生成符合正太分布的随机数;
2、通过正太分布随机数生成符合均匀分布的随机数;
3、生成指定分布的随机数
4、...........


参考:
1、Fitness proportionate selection
2、关于按概率生成随机数的问题的算法
3、根据相应概率产生随机数
4、生成特定分布随机数的方法(扩展阅读
5、继续随机数:接受/拒绝方法(标准正态分布)(扩展阅读
6、概率算法-均匀分布产生正态分布(扩展阅读
7、花式生成正态分布(扩展阅读)(推荐
8、C++ 生成随机数-GitHub(扩展阅读



请使用浏览器的分享功能分享到微信等