为什么C++不直接提供一个产生随机数的函数?

来源:互联网 发布:淘宝店主在哪里进货 编辑:程序博客网 时间:2024/05/15 12:31
只要了解一些C++的程序员都知道如何使用随机数:
#define MAX 100srand( (unsigned)time(NULL));rand() % MAX

先产生一个种子,一般是用时间,然后将rand()产生的随机数取想要得到最大值的模。

鉴于这段代码差不多已经成为定式,但是为什么不直接提供一个产生随机数的函数呢?

首先说明一下计算机产生随机数的原理。实际上,计算机产生的随机数并不是真正的随机数,而是伪随机数。是使用递推公式计算出来的整数序列,在我们使用的长度范围内,看似均匀分布。既然是递推公式,就需要一个初始值,叫做种子。因此同样的初始值一定产生同一样的序列。这就是下端代码总产生相同的随机数序列的原因。

for (int i = 0; i < 30; i++) {printf(" %d \n", rand() % MAX);}

因此一般使用时间作为种子。就是srand((unsigned) time(NULL)); 之所以需要使用者每次都指定种子的原因是,如果系统默认使用了时间作为种子,而不给用户选择的机会,那么在调试某些不重现的Bug的时候会引起不便。

另外要注意的是,设置种子和产生随机数是两个不同的操作,我们使用的随机数序列是指对于同一个种子不断产生的序列是伪随机的,而对于不同种子产生的第一个随机数不是随机的。因此像下边这样使用是不正确的:

for (int i = 0; i < 30; i++) {int seed = (unsigned)time( NULL );srand( seed );printf("%d - %d \n", seed, rand() % MAX);}
1368927451 - 17
1368927451 - 17
1368927451 - 17
1368927451 - 17
1368927451 - 17
.........

由于计算机运算的太快,使用(unsigned)time( NULL )产生的是以秒为单位的整数,没有来得及改变,因此每次都是用同一个种子,所以在一定循环内每次产生的第一个随机数都一样。像这样使用也是不正确的:

for (int i = 0; i < 30; i++) {srand( i );printf("%d \n", rand() % MAX);}

应该将种子的设置放在循环外边:

srand( (unsigned)time(NULL));for (int i = 0; i < 30; i++) {printf("%d \n", rand() % MAX);}