5.9 随机数生成

from http://www.learncpp.com/cpp-tutorial/59-random-number-generation/

通常在游戏,统计模型程序和科学模拟中会用到随机事件。

而由于计算机的本质结构决定计算机只能生成伪随机数据。

伪随机生成器,设定一个初始值(seed),对它进行操作形成不同的数值,让它看上去与初始值没有联系。如果算法足够复杂,将同样的算法用到最后生成的数字,这样就能够产生一些列看上去随机的数值。

下面是一个产生100个伪随机数的程序:

1.

   1: #include <stdafx.h>
   2: #include <iostream>
   3: using namespace std;
   4:  
   5: unsigned int PRNG()
   6: {
   7:     // our initial starting seed is 5323
   8:     static unsigned int nSeed = 5323;
   9:  
  10:     // Take the current seed and generate a new value from it
  11:     // Due to our use of large constants and overflow, it would be
  12:     // very hard for someone to predict what the next number is
  13:     // going to be from the previous one.
  14:     nSeed = (8253729 * nSeed + 2396403);
  15:  
  16:     // Take the seed and return a value between 0 and 32767
  17:     return nSeed  % 32767;
  18: }
  19:  
  20: int main()
  21: {
  22:     // Print 100 random numbers
  23:     for (int nCount=0; nCount < 100; ++nCount)
  24:     {
  25:         cout << PRNG() << "\t";
  26:  
  27:         // If we've printed 5 numbers, start a new column
  28:         if ((nCount+1) % 5 == 0)
  29:             cout << endl;
  30:     }
  31: }

事实上我们这个例子并不是很好,但是它足够用来说明伪随机数是如何产生的。

 

C++产生伪随机数

语言中有内置的随机数生成器,它需要两个独立的函数组合使用。

srand() 用来设置初始seed。srand()通常只调用一次。

rand()生成序列中的下一个随机值。

2.

   1: #include <iostream>
   2: #include <cstdlib> // for rand() and srand()
   3: using namespace std;
   4:  
   5: int main()
   6: {
   7:     srand(5323); // set initial seed value to 5323
   8:  
   9:     // Print 100 random numbers
  10:     for (int nCount=0; nCount < 100; ++nCount)
  11:     {
  12:         cout << rand() <<“\t”;
  13:         
  14:         // If we've printed 5 numbers, start a new column
  15:         if ((nCount+1) % 5 == 0)
  16:         cout << endl;
  17:     }
  18: }

rand()产生的伪随机数的范围在0到RAND_MAX之间,通常它的值在cstdlib中为32767.

通常我们并不想要这个范围内的随机值。我们想要两个nLow和nHigh范围内。如1-6.

3.

   1: // Generate a random number between nLow and nHigh (inclusive)
   2: unsigned int GetRandomNumber(int nLow, int nHigh)
   3: {
   4:     return (rand() % (nHigh - nLow + 1)) + nLow;
   5: }

当我们反复运行第2个程序的时候,发现每次的结果都是相同的。由于我们每次设置的seed都是相同的。因此我们使用了time()函数来产生seed。

   1: #include <stdafx.h>
   2: #include <iostream>
   3: #include <cstdlib> // for rand() and srand()
   4: #include <ctime> // for time()
   5: using namespace std;
   6:  
   7: int main()
   8: {
   9:  
  10:     srand(time(0)); // set initial seed value to system clock
  11:     for (int nCount=0; nCount < 100; ++nCount)
  12:     {
  13:         cout << rand() << "\t";
  14:  
  15:         if ((nCount+1) % 5 == 0)
  16:             cout << endl;
  17:     }
  18: }

 

怎样的伪随机生成器算是好的呢?

1)生成器会以相同的概率产生每一个数值。

2)随机序列的下一个数字不能明显、容易被预测

3)随机数生成器产生的数值有一个好的分布,忽而小,忽而大,让人感觉是随机的。

4)所有的伪随机生成器都是周期性的

 

rand()函数只是一个普通的伪随机生成器

大多数rand()都是使用Linear Congruential Generator方法实现的。

由于RAND_MAX通常是32767,意味着如果我们想要更大的范围就会不适合了。同时,rand()也不适合产生浮点型随机值如0.0-1.0. 同时rand()相对于其他算法拥有一个短的周期。

可以使用Mersenne Twister,它具有更好的结果,同时使用相对简单。

你可能感兴趣的:(随机数)