在应用编程中可能会用到随机数,例如抽奖小程序。随机数是随机出现,没有任何规律的一组数列。在编程当中,是没有办法获得真正意义上的随机数列的,这是一种理想的情况,程序当中想要使用随机数列,只能通过算法得到一个伪随机数序列, 那在编程当中说到的随机数,基本都是指伪随机数。我们所熟悉的常用的是通过rand()和srand()函数生成随机数。
下面是两个函数的原型:
#include<stdlib.h> //rand()和srand()函数需要包含此头文件
int rand(void)
//参数:参数为空
//返回值:为一个介于0到RAND_MAX的值,RAND_MAX是一个常量,它的默认值在不同的环境中会有所不同
//但至少是32767
void srand(unsigned int seed)
//参数:参数是unsigned int类型,是一个整型值,用于伪随机数生成算法播种,初始化rand()初始值
//返回值:不返回任何值
rand()函数产生随机数是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态分布,从而相当于产生了随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统。
用户未设定随机数种子时,系统默认的随机数种子为1。如果随机数种子相同, 那么每一次启动应用程序所得到的随机数序列就是一样的,下面通过在VS2022_x64环境中运行测试程序观察此现象:
![](https://i-blog.csdnimg.cn/blog_migrate/22c29e7f1f4c1c7a4565e61d391ab0a0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7ab1364d8fa1878960e2d0b00532afbe.png)
结论:通过图1和图2两次生成随机数的结果可知仅使用rand()函数每次生成的数据序列是相同的,也就是在调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。而使用相同种子相同的数调用srand()会导致相同的随机数序列被生成。
系统在调用rand()之前都会自动调用srand(),如果用户在rand()之前曾调用过srand()给参数seed制定了一个值,那么rand()就会将seed的值作为产生伪随机数的初试值;而如果用户在rand()前没有调过srand(),那么系统默认将1作为伪随机数的初始值。如果给了一个定值,那么每次rand()产生的随机数序列都是一样的。
所以为了避免上述情况,需要在每次执行程序时调用srand()产生不同的种子,因此通常用时间戳来产生种子,这样就可以使得程序每次运行所得到随机数序列不同。注意srand()一定是配合rand()使用的,srand()可以放在程序最开始生成种子,不要每一次生成随机数都生成种子。
什么是时间戳?
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。时间是一直在变化的,因此用时间戳来做srand()的参数就可以得到合理的随机数。(计算机具备时间戳转换工具)
怎么用时间戳来产生种子?
首先需要了解下面这个C库函数:
#include<time.h> time_t time(time_t *seconds) //参数:seconds -指向类型为time_t的对象的指针,用来存储seconds的值 //返回值:返回自1970-01-01 00:00:00起经过的时间,以秒为单位
需要注意time()函数的返回类型为time_t类型(time_t被定义为长整型),而srand()函数的参数类型为unsigned int类型,因此调用srand()函数时需要强制类型转换,即srand((unsigned int)time(0))或者srand((unsigned int)time(NULL))。
NULL的定义:#define NULL ((void *)0)
至此,关于在 Linux 下使用随机数就介绍这么多,产生随机数的 API 函数并不仅仅只有这些, 除此之外,譬如还有 random()、srandom()、initstate()、setstate()等。
产生随机数的用法总结:
1) 给srand()提供一个种子,它是一个unsigned int类型,通常使用time()函数返回的时间戳;
2) 调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到RAND_MAX之间);
3) 根据需要多次调用rand(),从而不间断地得到新的随机数。
测试程序:
#include<stdio.h>
#include<time.h>
int main()
{
int i = 0, j = 0;
double k = 0.0;
srand((unsigned int)time(NULL));
//取1-100之间的随机数
printf("生成1-100随机数:");
for (int j = 0; j < 5; j++)
{
i = (rand() % 100) + 1;
printf("%d ", i);
}
printf("\n");
//取0-1之间的浮点数
printf("生成0-1随机数:");
for (int j = 0; j < 5; j++)
{
k = rand()/32767.0;
printf("%lf ", k);
}
return 0;
}
测试结果:
![](https://i-blog.csdnimg.cn/blog_migrate/52f44a0e50789aa2b93df83e6ed3005c.png)
附:(C库函数查询网址)
1、MSDN(Microsoft Developer Network)
2、www.cplusplus.com
3、http://en.cppreference.com(英文版)
4、http://zh.cppreference.com(中文版)