Chinaunix首页 | 论坛 | 博客
  • 博客访问: 243849
  • 博文数量: 62
  • 博客积分: 973
  • 博客等级: 准尉
  • 技术积分: 530
  • 用 户 组: 普通用户
  • 注册时间: 2011-11-16 23:25
文章分类

全部博文(62)

文章存档

2013年(1)

2012年(14)

2011年(47)

分类: C/C++

2013-01-30 16:19:46

http://www.cnblogs.com/thu539/archive/2011/11/14/2247717.html

提到生成随机数,大多数人想到的是调用C++中的rand()函数,但是这里有个问题,rand()只能产生0~RAND_MAX(如在Visual Studio 2010上面最大为0x7FFF,即32767), 如果需要产生的随机数范围是0~232-1,则rand()函数会力不从心,需要使用其他更有效的方法来实现32位随机数的生成。

   本文采用三种方法,分别为Mersenne twister算法,调用Windows API CryptGenRandom函数来生成随机数,采用三个rand()生成的数字来拼合为一个数字。本文对这三种方法分别进行了介绍,并在实验中使用这三种方法分别生成了一百万个随机数,并画出了三种生成方法的数字分布图。

一.三种方法的介绍 

  1. Mersenne twister号称是目前最好的随机数生成算法,它是由Takuji Nishimura 和 Makoto Matsumoto于1997年开发的一种随机数生成方法,它基于有限二进制字段上的矩阵线性再生,可以快速产生高质量的伪随机数,该算法的循环周期为219937-1。Mersenne twister这个名字来自周期长度通常取Mersenne质数这样一个事实,常见的有两个变种Mersenne Twister MT19937和Mersenne Twister MT19937-64,本文实验的就是MT19937算法。关于这种算法更详细的介绍,可以参考博客http://www.cppblog.com/Chipset/archive/2011/11/01/73177.htmlhttp://www.cppblog.com/Chipset/archive/2009/01/19/72330.html,如果对算法本身感兴趣,可以去该算法作者的页面去下载代码实现,如果希望看到关于这个算法的论文,,这篇文章或许会有帮助。


  1. 产生size个32位随机数的函数,调用MT19937中的随机生成方法

  2. bool ProduceRandomNumberMT19937(UINT* RandomArray,UINT size)
  3. {
  4.     time_t t;
  5.     init_genrand((unsigned)time(&t));
  6.     if(RandomArray==NULL)
  7.     {
  8.         return false;
  9.     }
  10.     for(UINT i=0;i<size;i++)
  11.     {
  12.         RandomArray[i]=genrand_int32();
  13.     }
  14.     return true;
  15. }

2. 第二种方法采用的是调用Windows API CryptGenRandom方法,这个函数是windows用来提供给生成随机密码数字功能所用,一般应用在随机给vector赋值或者生成噪声点时使用。这个函数所提供的随机性要好于rand()函数。具体关于这个函数的信息,请关注msdn关于这个函数的解释


  1. 使用CryptGenRandom函数生成size个32位随机数的函数

  2. bool ProduceRandomNumberCrypt(UINT* RandomArray,UINT size)
  3. {
  4.     HCRYPTPROV hCryptProv;
  5.     if(CryptAcquireContext(
  6.        &hCryptProv,
  7.        NULL,
  8.        NULL,
  9.        PROV_RSA_FULL,
  10.        0))
  11.     {
  12.         //printf("CryptAcquireContext succeeded. \n");
  13.     }
  14.     else
  15.     {
  16.         //MyHandleError("Error during CryptAcquireContext!\n");
  17.     }

  18.     if(CryptGenRandom(
  19.        hCryptProv,
  20.        size*sizeof(UINT),
  21.        (BYTE*)RandomArray))
  22.     {
  23.          //printf("Random sequence generated. \n");
  24.          return true;
  25.     }
  26.     else
  27.     {
  28.          //printf("Error during CryptGenRandom.\n");
  29.          return false;
  30.     }
  31. }

3. 第三种方法,是使用rand()函数随机生成的三个数来拼接成一个32位数字的方法,这种方法实现起来也很简单,但是由于rand()的随机性并不是很好,所以不推荐这种方法。一个32位随机数由(rand()<<17)|(rand()<<2)|(rand())方法拼合而成。实现代码如下:

  1. 使用三个rand()生成伪随机数生成一个32位随机数

  2. bool ProduceRandomNumberCRand(UINT* RandomArray,UINT size)
  3. {
  4.     time_t t;
  5.     srand((unsigned)time(&t));
  6.     if(RandomArray==NULL)
  7.     {
  8.         return false;
  9.     }
  10.     for(UINT i=0;i<size;i++)
  11.     {
  12.         RandomArray[i]=(rand()<<17)|(rand()<<3)|(rand());
  13.     }
  14.     return true;
  15. }

二. 三种方法的实验结果

   每种方法均进行了100万个32位随机数的生成实验,将这100万个随机数分为0xFFF个组,组之间的间隔为0xFFFFF,然后绘出各个组生成随机数的分布图。

   1. MT19937算法的分布

  2. CryptGenRandom函数生成随机数分布图

  3. 使用三个rand()数生成一个32位随机数的分布图

 










阅读(3384) | 评论(0) | 转发(0) |
0

上一篇:Autodesk 的 c++题(2007.05)

下一篇:没有了

给主人留下些什么吧!~~