在C语言中,ANSIC C程序库提供rand()函数来产生随机数。但事实上,rand()是并不是一个真正的随机数产生器,即可以预测随机序列的顺序,在默认随机种子情况下产生0~99之间的随机数,其随机序列为{83,86,77,15,……},比如以下程序:
#include<stdio.h> #include<stdlib.h> int main(){ int num; printf("A set of random numbers:\n"); for(int i = 0; i < 10; i++){ num = rand()%100; //产生0-99之间的随机数; printf("%d ",num); } putchar('\n'); return 0; }
编译、执行结果:
可以看出,在执行三次情况下,rand()产生的随机序列都是一样的。这是因为,rand()使用的是产生伪随机数的“魔术公式”,它的随机数种子是一直没有变的,所以每次产生的随机序列是一样的。在调用rand()函数之前,可以使用srand()函数设置随机数种子,如果没有设置随机数种子,rand()函数在调用时,自动设计随机数种子为1。随机种子相同,每次产生的随机数也会相同。rand()函数被包含在头文件<stdlib.h>中。
如果想要构造每次产生不同的随机数序列的函数,则需要引入一个不断变化的随机种子。最常用的就是时间变量,利用时间函数time()获取系统时间(其返回值time_t一定是数值类型)。time()的参数是一个time_t类型对象的地址,时间值则存储在该地址中。所以,可以使用空指针0或者NULL作为参数。此时,时间通过返回值机制提供。time()函数包含在头文件<time.h>中。写一个简单地程序说明time()函数;
#include<stdio.h> #include<time.h> int main(){ int num1,num2; printf("The return value of time:\n"); num1 = time(0); num2 = time(NULL); printf("%d,%d\n",num1,num2); return 0; }
编译并执行三次:
可以看出,使用空指针0或者NULL作为参数得到的结果是一致的,但是每次执行的结果不一样。将时间函数作为随机种子:
#include<stdio.h> #include<stdlib.h> #include<time.h> int main(){ int num; srand(time(0)); //将时间函数传入到随机数产生函数; printf("A set of random numbers:\n"); for(int i = 0; i < 10; i++){ num = rand()%100; printf("%d ",num); } putchar('\n'); return 0; }
执行结果:
在将时间函数作为随机种子之后,可以发现每次产生的随机序列都不在一样。此时。需要考虑如何产生一定范围内的随机数。rand()产生的是从0到RAND_MAX(32767)之间的伪随机数(正整数),如果我们想要1~100之间的随机序列呢?这里我们用到了取余%运算,一个正整数对5取模运算,产生的余数范围必在0~4之间。所以,对正整数进行模a的取余运算,得到的余数范围在0~a-1,如果对取余运算的结果加上b,得到的结果就在b~a+b-1之间。所以,我们要得到[M,N]区间内的随机数,函数rand()就要对(N-M+1)取余运算,再加上M。
编写一个输出100个[1,10]区间内的随机序列产生程序。
#include<stdio.h> #include<stdlib.h> #include<time.h> int main(){ int num; srand(time(0)); printf("A set of random numbers:\n"); for(int i = 0; i < 100; i++){ num = rand()%10+1; printf("%d ",num); } putchar('\n'); return 0; }
编译并执行两次: