不废话,直接上干货。
目录
首先我们需要知道两个函数,即srand和rand函数。
这两个函数的头文件是 :#include <stdlib.h>
先来看看rand函数:
1.rand函数的声明如下:
int rand(void);
2.rand会返回一个范围在 0 到 RAND_MAX 之间的伪随机数。RAND_MAX 是一个常量,它的默认值在不同的实现中会有所不同,但是值至少是 32767。
3.伪随机数并不是真正的随机,在rand函数的内部,是通过一个公式计算出一个值作为随机值,下次再调用rand的时候,再把这个随机值作为参数传给这个公式计算出一个新的随机值,周而复始。若代入公式的值一直不变,计算出的随机值就不会变化。
公式如下:
y=ax+b(mod n)其中,n一般是一个很大的素数,几万。
a也是大素数。而且a,b,n都是常数。所以rand的产生决定于x,
他被称为seed(种子)。
所以只有rand函数是不够的!!!
4.在C库中,是通过一个静态全局变量来作为“种子”,而这个“种子”的值是通过srand函数改变的,如果不写srand函数,这个“种子”值默认赋值为1。这就解释了“为何不写srand函数,rand函数就会生成伪随机数”,因为程序只要重新开始运行,“种子”值就会被默认赋值为1,那么通过公式算出来的序列肯定就一直相同了。
所以如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。
5.代码演示:
一直都是41的值。
这时候我们就讲讲srand函数:
1.srand函数的声明如下:
void srand(unsigned int seed);
2.C 库函数 void srand(unsigned int seed) 播种由函数 rand 使用的随机数发生器。
seed的变化下,rand函数会生成各种数值。seed不变,rand就不会变化。srand通过播种不同的种子(seed),就会生成不同的rand。
3.如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
4.代码演示:
此时我们要引入time函数来设置变量
1.
time函数的头文件是#include <time.h>
2.这里先介绍几个时间概念:
1:Coordinated Universal Time(UTC):
协调世界时,又称世界标准时间,也即格林威治标准时间(Greenwich Mean Time,GMT),中国内地的时间与UTC得时差为+8,也即UTC+8,美国为UTC-5。
2:Calendar Time:
日历时间,是用"从一个标准时间点到此时的时间经过的秒数"来表示的时间。标准时间点对不同编译器可能会不同,但对一个编译系统来说,标准时间是不变的。一般是表示距离UTC时间 1970-01-01 00:00:00的秒数。
3:epoch:
时间点。在标准c/c++中是一个整数,用此时的时间和标准时间点相差的秒数(即日历时间)来表示。
4:clock tick:
时钟计时单元(而不叫做时钟滴答次数),一个时钟计时单元的时间长短是由cpu控制的,一个clock tick不是cpu的一个时钟周期,而是c/c++的一个基本计时单位。
3.函数原理
函数原型: time_t time(time_t *timer)
参数说明: timer=NULL(空指针)时得到当前日历时间(从1970-01-01 00:00:00到现在的秒数),timer=时间数值时,用于设置日历时间,time_t是一个unsigned long类型。如果 timer不为空,则返回值也存储在变量 timer中。
函数功能: 得到当前日历时间或者设置日历时间
函数返回: 当前日历时间
从上面可以知道括号里填空指针和具体地址返回的数值都是一样的,即当前日历时间(从1970-01-01 00:00:00到现在的秒数)
代码演示:
4.我们把time函数作为种子放到srand里面,就会因为时间不断变化而使种子不断变化。
5.注意事项:
第一,srand传参传time(NULL)的话会有个小缺陷,就是如果同一秒内调用两次或以上rand函数,生成的随机数序列仍然是相同的;
第二,伪随机数的产生依赖与种子,种子的时间间隔至少1s就可以生成不同的随机数。也不是不能放在一个同函数同一个语句中,只要间隔1秒就行,比如机子很破,跑个for要1秒,也能生成不同随机值。所以srand函数应该放到循环外部。
代码演示:
两者对比
代码综合:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
//time_t t1, t2; //分别声明三种使用方式的赋值对象
//t1 = time(NULL); //括号里写NUll和数字实际上没有区别,两者都是计算当下到1970的秒数
//time(&t2); //time函数先找到t2的地址,再把当下到1970的秒数传给t2
//
//printf("t1=%ld\n", t1);
//printf("t2=%ld", t2);
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++)
{
printf("%d\n", rand());
}
printf("%d\n", rand());
return 0;
}