ANSI C库提供了rand()函数生成随机数。生成随机数有多种算法,ANSC I允许C实现针对特定机器使用最佳算法,在不同系统中生成相同的随机数。实际上,rand()生成的是伪随机数,即可预测接下来要生成的数字,但数字在其取值范围内均匀分布。
rand()函数
包含在“stdlib.h”头文件中。
函数原型 int rand(void)
为了掩饰程序内部运行的情况,下面的代码并不是编译器内置的函数。
static unsigned long int next = 1;
unsigned int rand1(void)
{
next = next * 1103515245 + 12345; //魔术公式
return (unsigned int)(next / 65536) % 32678;
}
函数开始于一个“种子”数字,该数字被函数使用后,生成一个新数,新数又成为函数的种子,供下一次使用,以此类推。不难发现,随机数函数并不是随机的,只不过这个函数的周期特别的大,模拟随机的效果特别好,这也是魔术公式的神奇之处。
直接使用的话函数会生成0-RAND_MAX(32767)之间的随机数,要想生成指定区间的随机数,可以使用求余运算。比如生成[a,b]之间的随机数,则rand()%(b-a+1)+a,因为计算机的区间都是左开右闭的。
值得注意的是,多次运行程序后,就会发现,产生的随机数完全相同,这也是伪随机的一个表现,因为种子的初始值相同都是1。
如何让每次运行产生不同的随机数呢?很明显,只需要重置种子就可以解决这个问题。ANSI C库为我们提供了srand()函数。
srand()函数
包含在“stdlib.h”头文件中。
函数原型 void srand(unsigned int seed)
unsigned long int next = 1;
unsigned int rand2(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32678;
}
void srand1(unsigned int seed)
{
next = seed;
}
因为next为内部链接的文件作用域静态变量,所以rand2()和srand1()都可以使用它,但是其他文件无法访问。
但是如果每次使用随机数函数都要人为对种子赋予新值来获得不同的随机数的话,显然不太方便,所以C允许访问一些可变的量,可以用这些值初始化种子值。
ANSI C库提供了一个time()函数。
time()函数
包含在“time.h”头文件中。
函数原型 time_t time(time_t *timer)
time()函数用来返回系统时间,返回值是一个可进行运算的类型,并且其值随着时间变化而变化。time()返回值类型是time_t,具体类型与系统有关。但这不重要,我们可以用强制类型转换。
timer=NULL时得到当前日历时间(从1970-01-01 00:00:00到现在的秒数),timer=时间数值时,用于设置日历时间。如果timer不为空,则返回值也储存在变量timer中。
time()函数有两种使用方法:
(1)time(NULL)或time(0);
(2)time(&t);
将变量t的地址作为实参传递给time()函数,函数自动把结果传递给t,不需要额外的赋值语句。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 10
int main()
{
//产生十个min到max间的随机数
int i, max, min;
scanf("%d%d", &min, &max);
srand((unsigned int)time(0));
for (i = 0;i < N;i++)
{
printf("%d ", rand() % (max - min + 1) + min);
}
return 0;
}