前言
随机数这个概念我们都熟悉,就是数字的生成是随机的不确定的,不能掌控的。
而计算机生成的随机数是伪随机数,为什么说是伪随机数呢?
因为数字的生成是由人设计的算法生成的,就是说,本质上,生成的数字是由人来设计的,由固定的计算得来。
虽然如此,但也是可以随机的不可掌控,怎么回事呢?我们来了解下随机数生成的两个函数。
一、rand()
int __cdecl rand()
这就是随机函数rand()
的原型,定义在头文件stdlib.h
中。
rand()
函数的使用很简单,它会产生一个0~RAND_MAX范围内的数值,stdlib.h
中
#define RAND_MAX Ox7FFF
数值的范围可以通过取余,加减乘除等进行调整。
简单使用测试:
#include <iostream>
#include <cstdlib> //c++中的stdlib.h
using namespace std;
int main(){
int n=6;
while(n--){
cout<<rand()<<endl;
}
system("pause");
return 0;
}
以上会生成6个随机数,如果你运行多次就会发现,每次生成的6个数字都是相同的!为什么都是相同的呢?
rand()
函数是依靠一个叫做send
种子的初始值来生成随机数的,这也就是开头我解释为伪随机数的原因。
既然依靠种子,那只要每次给的种子都不同,生成的随机数就不会是相同的,如果不设置,种子默认为1。
怎么设置种子呢?看rand()
函数原型也没见参数传递啊,种子的设置有点特殊,是通过srand()
函数设置的。
二、srand()
void __cdecl srand(unsigned int _Seed)
这就是srand()
的函数原型,同样定义在stdlib.h
中。
srand()
的使用很简单,只要在rand()
前用srand()
设置种子就可以了,参数为无符号整数。
简单测试使用
#include <iostream>
#include <cstdlib> //c++中的stdlib.h
using namespace std;
int main(){
unsigned int m; //或者int m 都行,类型会隐式转换
cin>>m;
srand(m);
int n=6;
while(n--){
cout<<rand()<<endl;
}
system("pause");
return 0;
}
这样就会根据你输入种子的不同而产生不同的随机数了。
但你说,这样好麻烦,要手动输入种子,不能有个自动的么?有,一般都是通过time()
这个函数生成种子配合使用。
三、time()
typedef long long __time64_t
typedef __time64_t time_t
time_t __cdecl time(time_t *_Time)
这个就是time()
的函数原型,这是个用来获取时间的函数,因为时间不停地变动,所以每次生成的种子都会不一样,就可以产生不同的随机数。
可以看出它会返回一个long long
类型的数字回来。
在32位机上
long 4个字节
long long 8个字节
在64位机上
long 8个字节
long long 16个字节
是不是觉得数字有点大啊,我也觉得数字有点大,毕竟srand()
的传入参数为unsigned int
,才4个字节,不过有类型转换,需要的是一个种子,不关乎是否精度损失,这样的损失可能正好匹配随机这个概念,但精度的损失也是认为设计的就是了。
time()
这个函数究竟怎么使用我也不是很清楚,不过只要用time(0)
作为srand()
的传参就可以了。
简单实用测试:
#include <iostream>
#include <cstdlib> // srand和rand的头文件
#include <ctime> // time的头文件
#define MAXNUM 7
using namespace std;
int main()
{
int num;
cout << "what the number is you want to get?\ninput:";
cin >> num;
cout << "The " << num << " number will be in 0~6:\n";
// 以time(0)返回值作为随机种子
// 原函数
/*
typedef long long __time64_t
typedef __time64_t time_t
time_t __cdecl time(time_t *_Time)
*/
/*
void __cdecl srand(unsigned int _Seed)
int __cdecl rand()
*/
srand(static_cast<unsigned int>(time(0)));
while (num--)
{
// 以随机种子产生伪随机数,取余产生一定范围内的数值
cout << rand() % MAXNUM << endl;
}
system("pause");
return 0;
}
结语
实际上我们可以想到,即使用time()
获得的时间也是我们人为定义的,可以假想下,只要知道时间为多少,就可以以此来获得你的随机数了,所以说是伪随机数是没有问题的。
但你会说谁这么无聊搞这个,放心,无聊的人总不会缺少的。
其实你可以让让产生的随机数作为种子,这样多次嵌套,就很难摸得到你的随机数了。