引言
初学者大部分对这两个函数的意义都不甚了解,以及不明白为什么需要srand()函数来播种,这里会对两函数的意义进行解释,让大家明白两函数搭配的作用,并对伪随机数以及真随机数进行讲解,最后会对随机数生成的原理进行一些探讨,希望对大家的学习理解有所帮助
rand()函数
格式:
int rand(void); //void表示不需要参数
当没有参数时rand() 会随机生成一个位于 0 ~ RAND_MAX 之间的整数。
RAND_MAX 是 <stdlib.h> 头文件中的一个宏,它用来指明 rand() 所能返回的随机数的最大值。C语言标准并没有规定 RAND_MAX 的具体数值,只是规定它的值至少为 32767。在实际编程中,我们也不需要知道 RAND_MAX 的具体值,把它当做一个很大的数来对待即可。
用法(求余):
如下取值范围为j ~ i :
rand() % (i - j + 1) + j; //i表示随机数生成的最大值,j表示随机数生成的最小值
实例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n",rand());
return 0;
}
运行后会发现每次结果都是相同的,原因是rand()函数生成的是伪随机数(即通过算法生成,是正态分布的,并不是真正的随机),而非真随机数,那么接下来就讲讲随机数
随机数
首先讲讲什么叫真随机数和伪随机数,按照定义来讲(WIKI百科)
1.真随机数:
真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。 这样的随机数生成器叫做物理性随机数生成器,它们的缺点是技术要求比较高。 在实际应用中往往使用伪随机数就足够了。 这些数列是“似乎”随机的数,实际上它们是通过一个固定的、可以重复的计算方法产生的。
2.伪随机数:
伪随机数是使用一个确定性的算法计算出来的似乎是随机的数序,因此伪随机数实际上并不随机。在计算伪随机数时假如使用的开始值不变的话,那么伪随机数的数序也不变。伪随机数的随机性可以用它的统计特性来衡量,其主要特征是每个数出现的可能性和它出现时与数序中其它数的关系。伪随机数的优点是它的计算比较简单,而且只使用少数数值很难推算出计算它的算法。一般人们使用一个假的随机数,比如电脑上的时间作为计算伪随机数的开始值。
从这里的定义我们可以知道,计算机生成的伪随机数其实是有规律可循的,并不是完全的随机,只不过它的循环周期可能比较长罢了
srand()函数
通过上面对随机数的讲解,相信大家也可以明白,仅仅是通过rand()函数,每次计算机生成的数值都是固定的,那么我们便需要想办法让rand()函数每次生成的数值是伪随机的,这样每次生成的值才不会重复,于是便需要用到srand()函数
用法:
void srand (unsigned int seed);
通过srand()函数来初始化随机种子,这个种子会对应一个随机数,如果使用相同的种子后面的 rand() 函数会出现一样的随机数,如: srand(1); 所以我们通常会使用time()函数来返回自 1970 年 1 月 1 日 到现在当前的时间,而我们当前的时间又是每秒都在变动的,所以由时间播种生成了伪随机数
实例:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
srand((unsigned)time(NULL));
printf("%d\n",rand());
return 0;
}
执行后发现每次生成的值不再重复了
拓展思考
相信细心的朋友也考虑到了一个问题,既然通过time()函数得到的时间是根据当前时间的来的,那么如果当前时间没有发生变化的话岂不是得到的是相同的值?
这里通过for循环来进行演示
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i;
for(i = 0; i < 10; i++)
{
srand((unsigned)time(NULL));
printf("%d\n",rand());
}
return 0;
}
这里我们将srand()函数放在for循环语句内,而for循环单次循环的时间是远小于1s的,那么srand()函数内的种子便没有发生变化,相同的种子执行结束后每次得出的结果自然是相同的,而如果将srand()函数放到for语句之外,每次生成的结果又不重复了,这样我们就既能输出一组随机数,又能避免重复了
别急还没完,到这里相信有人和我一样又考虑到,按道理来说实例这点程序,放到外面难道就会执行时间小于1s?然后导致播种每次都能是不同种子结果才会不同么?
仔细思考后以为不然,个人认为rand()这个函数在播种以后其实是生成了一个伪随机数序列,而连续调用这一种子,第一次输出的是序列中第一个值,第二次输出的是序列中第二个值,这样依次下去输出,所以在for循环外时可以得到不同的随机值;但在for循环内的话由于执行速度太快小于1s,相当于每次都连续播种了同一个种子,这样每次只能输出序列的第一个值,所以结果当然是几个同样的值
实例验证:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i;
time_t begin,end;
begin = time(NULL);
//在循环体外部初始化种子
srand((unsigned)time(NULL));
for(i = 0; i < 10; i++)
{
printf("%d ",rand());
}
putchar('\n');
//在循环体内部初始化种子
for(i = 0; i < 10; i++)
{
srand((unsigned)time(NULL));
printf("%d ",rand());
}
putchar('\n');
//未初始化种子
for(i = 0; i < 9; i++)
{
printf("%d ",rand());
}
putchar('\n');
end = time(NULL);
printf("程序执行所花费的时间为:%ld\n",end - begin);
return 0;
}
输出结果如图:
首先我们可以看到计算程序执行所花费的时间为0,说明程序执行时间小于1s,然后再对比程序的执行结果,循环内得出的结果和循环外结果均与序列的第一个值相同,而第三个循环体未初始化种子,那么种子延续上面初始化的种子,输出的9个值与循环体外结果序列的后9个值依次相同,猜想的原理得到验证文章来源:https://www.toymoban.com/news/detail-824798.html
文章来源地址https://www.toymoban.com/news/detail-824798.html
到了这里,关于rand()函数与srand()函数以及随机数种子详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!