两种不同随机算法设计理念

转自http://software.intel.com/zh-cn/blogs/2014/02/13-0/?utm_campaign=CSDN&utm_source=intel.csdn.net&utm_medium=Link&utm_content=others-suanfa

随机算法在程序设计里的使用频度就不用我说了。一般我们用到的随机算法 都是伪随机算法,什么叫伪随机算法呢?伪随机算法意思是假如知道第一个随机种子和随机算法的话就可以推算出下一个随机数。通常我们程序里都是通过当前时间 作为随机函数的第一个随机种子,然后将随机函数返回的值作为下一个种子,随机函数是一个公用函数,每个用户的请求都会触发一个新的随机种子,所以说是随机 的。很多公司都有自己的一套随机算法,下面看一下一位前辈的总结。

    /********************************************************************

  参考:http://www.cppblog.com/Chipset/archive/2009/02/07/73177.html

 

  我们讲的随机数其实暗指伪随机数。提及随机数,不少朋友可能想到C语言的库函数rand(),rand()随机性太差,速度太慢。

  古老的LCG(linear congruential generator)代表了最好的伪随机数产生器算法。主要原因是容易理解,容易实现,而且速度快。

  这种算法数学上基于X(n+1) = (a * X(n) + c) % m这样的公式,其中:

    模m, m > 0

    系数a, 0 < a < m

    增量c, 0 <= c < m

    原始值(种子) 0 <= X(0) < m

  其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。

  

  一般而言,高LCG的m是2的指数次幂(一般2^32或者2^64),因为这样取模操作截断最右的32或64位就可以了。

  多数编译器的库中使用了该理论实现其伪随机数发生器rand()。下面是部分编译器使用的各个参数值:

  

  Source                           m            a            c          rand() / Random(L)的种子位

  Numerical Recipes                  

                                  2^32         1664525      1013904223    

  Borland C/C++                      

                                  2^32         22695477     1          位30..16 in rand(), 30..0 in lrand()

  glibc (used by GCC)                

                                  2^32         1103515245   12345      位30..0

  ANSI C: Watcom, Digital Mars, CodeWarrior, IBM VisualAge C/C++

                                  2^32         1103515245   12345      位30..16

  Borland Delphi, Virtual Pascal

                                  2^32         134775813    1          位63..32 of (seed * L)

  Microsoft Visual/Quick C/C++

                                  2^32         214013       2531011    位30..16

  Apple CarbonLib

                                  2^31-1       16807        0          见Park–Miller随机数发生器

 

*********************************************************************/

    再来看看linux内核提供的一个随机算法,linux下的随机数是通过你上次操作外围设备和这次的时间差产生的随机数。其实区别就在于随机种子的产 生。linux下将随机种子作为bytes流输出到/dev/random这个文件里,我们可以访问,并运用。下面我就通过linux提供的这个接口写个 dota下非常常用的命令,roll。相信玩dota的玩家都很熟悉吧,好的废话不多说,来看咱的roll随机程序。

 

[cpp]  view plain copy
 
  1. #include <stdio.h>  
  2. #include <sys/stat.h>  
  3. #include <sys/types.h>  
  4. #include <fcntl.h>  
  5. #include <unistd.h>  
  6. #include <assert.h>  
  7. /* return a random integer between Min and Max. inclusive. obtain 
  8.    randomness from /dev/random */  
  9. int random_number(int min, int max)  
  10. {  
  11.     /* store a file descriptor opened to /dev/random in a static variable 
  12.        ,that way ,we don't need to open the file every time this function is called. */  
  13.     static int dev_random_fd = -1;  
  14.     char* next_random_byte;  
  15.     int byte_to_read;  
  16.     unsigned random_value;  
  17.     /* make sure max is greater then min */  
  18.     assert(max > min);  
  19.       
  20.     /* if this is frist time the function is called, open a file descriptor to /dev/random. */  
  21.     if(dev_random_fd == -1){  
  22.         dev_random_fd = open("/dev/random", O_RDONLY);  
  23.         assert(dev_random_fd != -1);  
  24.     }  
  25.       
  26.     /* read enough bytes to fill an integer variable.*/  
  27.     next_random_byte = (char*)&random_value;  
  28.     byte_to_read = sizeof(random_value);  
  29.     /* loop until we'v readed enough bytes. Because /dev/random is filled from user genered action. 
  30.        the read may block or only return a single random byte at a time.*/  
  31.     do{  
  32.         int bytes_read;  
  33.         bytes_read = read(dev_random_fd, next_random_byte, byte_to_read);  
  34.         byte_to_read -= bytes_read;  
  35.         next_random_byte += bytes_read;  
  36.      }while(byte_to_read > 0);  
  37.     /* compute a random number in the correct range */  
  38.     return min + (random_value % (max - min + 1));  
  39. }  
  40. int main(int argc, char* argv[])  
  41. {  
  42.     /* int min = argv[1]; */  
  43.     int min;  
  44.     int max;  
  45.     if(argv[1] == 0x0)  
  46.     {  
  47.         max = 100;  
  48.         min = 0;  
  49.     }  
  50.     else if(argv[1] != NULL && argv[2] == NULL)  
  51.     {  
  52.         min = 0;    
  53.         max = atoi(argv[1]);  
  54.     }  
  55.     else  
  56.     {  
  57.         max = atoi(argv[2]);  
  58.         min = atoi(argv[1]);  
  59.     }  
  60.     int random_num = random_number(min, max);  
  61.     printf("You have tossed:%d/ttop limit is:%d/n", random_num, max);  
  62.     return 0;  
  63. }  

    我是在ubuntu9.04下gcc编译通过的,有兴趣的同学可以试试。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值