随机数生成

C语言提供两个随机数相关的函数,即 rand 和 srand。主要弄清楚它的伪随机,以及如何产生真正意义上的随机数。

1
int rand (void);		// 返回值是一个伪随机数

此数字由一种算法生成,该算法在每次调用时都会返回一系列明显不相关的数字。此算法使用种子生成序列,应使用下面的 srand 函数 将其初始化为某个独特的值。

1
void srand (unsigned int seed);	// 传递一个种子数

为什么说它是伪随机?

1
2
printf("first random number = %d\n", rand());
printf("second random number = %d\n", rand());

运行上面的函数你会得到两个随机数,但你再次运行你会发现还是之前得到的两个随机数,这就是说 rand() 得到的是伪随机的原因。当你确定种子的那一刻起,你后面生成的数字也就都被确定下来,这就是为什么伪随机的缘故。

下面通过 srand() 创建种子,看看现象:

1
2
3
4
5
6
7
8
9
srand(10);
printf("first random number = %d\n", rand());
srand(10);
printf("second random number = %d\n", rand());

/*
first random number = 71
second random number = 71
*/

没错,当你种子确定的那一刻,那么底层算法就已经帮你规定好后面顺序的所有数字该多少了。当你第一次规定种子为 10,那么获取随机数为 71,如果这个时候你重新规定种子为 10,那么再次获取随机数也还是71。

如何得到真正意义上的随机数?

既然,种子不同就会得到不同的随机数,那么时间是不断变化的,只要我们传入 每一刻的时间即可。

1
srand(time(NULL));

往后,你调用 rand 得到的必然就是随机数了。

注意:srand() 函数只需要在程序中调用一次即可,而 rand() 函数可以多吃调用生成随机数。

为什么srand()建议只调用一次?

频繁重置种子:如果你在短时间内多次调用 srand(time(NULL)),种子值可能不会发生变化(因为 time(NULL) 返回的是当前时间,单位是秒)。因此,随机数生成器会被重新初始化为相同的种子值,这会导致生成的随机数序列重复,从而降低随机性。

随机性降低:理想情况下,随机数序列应当尽可能不可预测。如果你不断地调用 srand 并使用几乎相同的种子,生成的随机数序列将会是相同的或高度相关的,这就违背了使用随机数的目的。

因此,避免多次调用 srand(time(NULL)),这样可以保持随机数序列的随机性和不可预测性。