一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情。
随机函数 rand()
首先明确计算机中没有真正的随机函数,而这些所谓的随机函数都是伪随机。
伪随机: 如果我们不改变随机函数的种子(这里的种子可以理解为随机函数的初始值),那么随机数的数序也不会改变,使用相同的随机函数种子每次我们都将得到同一组数序的随机数,这就是伪随机。(皇室战争手游中宝箱的获取就是伪随机)
rand() 函数定义
- 头文件:在C中为
#include<stdlib.h>;C++中为#include<cstdlib>,包含在#include<iostream>中 - 函数方法:
int rand(void); - 功能:无需函数参数,返回随机数范围
[0, RAND_MAX)左闭右开区间,RAND_MAX根据不同系统值不同。RAND_MAX最小值为(0x7fff),最大值为 (INT_MAX) - 若未调用初始化随机函数
srand(),系统会自动调用一次初始化随机函数srand(1)。
rand() 常用操作
rand() % x: 得到 左闭右开区间内的一个随机数(rand() % 10) / (double)9: 得到 区间内的一个随机小数(概率0%-100%)a + rand() % b:得到 左闭右开区间内的一个随机数
初始化随机函数 srand()
想要得到更进一步的随机数,就需要用到初始化随机函数 srand()。
srand() 函数定义
- 头文件与
rand()一致:在C中为#include<stdlib.h>;C++中为#include<cstdlib>包含在#include<iostream>中 - 函数方法:
void srand(unsigned int seed); - 功能:初始化
rand()函数的随机种子
如果每次使用相同数值的种子进行初始化,
rand()函数也将会产生同一组随机数值。例如我们每次都不调用srand()函数,那么系统每次都会自动调用一次初始化随机函数srand(1),也就是每次的初始化随机函数种子为1,那么我们每次使用的随机数值都是同一组。
srand() 常用的初始化随机函数操作
- 使用当前系统时间作为种子进行随机数发生器的初始化:因为每次调用
srand()函数的时间通常是不同的(运行时间需要间隔超过1秒),这样就可以保证每次的rand()函数产生的随机数值具有随机性了。
srand((unsigned)time(NULL));//time(NULL)也可以写成time(0)
调用 time(NULL) 的返回值(类型为 time_t )显式强转型成 unsigned int ,再传递给 srand() 函数(接收一个 unsigned int 参数)作为种子进行初始化随机函数。
关于 time() 函数
time() 函数是C标准库函数。
- 头文件:在C中需要添加头文件
#include<time.h>,C++中需要添加头文件#include<ctime> - 函数方法原形:
time_t time(time_t *t)(其中time_t就是long int) - 函数功能:这里的
time()函数如果传入的参数为NULL或者0,返回的是从00:00:00 GMT, January 1, 1970到现在所持续的秒数。
#include<bits/stdc++.h>
using namespace std;
int main(){
time_t t;
t = time(0);//同time(NULL)
printf("秒数为:%ld\n",t);
printf("当前时间:%s", ctime(&t));
return 0;
}
/*
运行结果:
秒数为:1649932240
当前时间:Thu Apr 14 18:30:40 2022
*/
time(0) 和 time(NULL) 函数可以获取当前的系统时间(但是获取的这个时间是从1970年1月1日0时0分0秒到目前为止所经过的秒数),ctime() 函数可以将 time_t* 类型转化为常规的时间格式,并且以字符数组类型作为返回值。char* ctime (const time_t *time),ctime 返回的是字符数组(字符串)类型。
随机函数的使用
蓄水池抽样算法
从前往后处理每个样本,每个样本成为答案的概率为 1/i,这样就能使得每个样本抽到的概率相同为 1/n
使得每个概率为 1/i 的做法:rand() % i == 0
代码部分
srand((unsigned)time(NULL));
int idx = 0;//开始只有一个,初始化idx为第一个下标
//随机抽取下标,范围在[0, n),左闭右开区间,%的数代表前面的个数
for(int i = 1; i < n; i++){
if(rand() % (i + 1) == 0) idx = i;
}
总结
计算机中没有真正的随机函数,也不能真正的产生随机数,但计算机中存在伪随机数序,我们利用伪随机数序和当前系统时间相结合,使用系统当前时间(时间是不断改变的)作为伪随机数序的随机种子,使得我们得到的数序能够更具有随机性。所以我们在使用 rand() 函数前通常都会先初始化随机函数,为了使得随机函数得到的数序不是同一段数序,初始化随机函数的种子也要更具有随机性,所以我们采用系统当前的时间作为初始化随机函数的种子。这就是我们常用的操作手法:srand((unsigned)time(NULL));
结束语
生活是一场充满未知的旅途。不要因为眼前的困境,就丧失对未来的期盼。以积极的心态,活出最佳状态,便是交给生活最好的答卷。心中有光,有所热爱。请相信,那些不期而遇的幸运,正在朝你奔来。