LV015-随机数
本文主要是用Linux系统中获取随机数的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。
一、随机数
在很多时候我们都有可能会用到随机数,就自己一个一个写吗?不可能的,这辈子都不可能自己写的,哈哈。
1. 伪随机数?
随机数是随机出现,没有任何规律的一组数列。在我们编程当中,是没有办法获得真正意义上的随机数列的,这是一种理想的情况,在我们的程序当中想要使用随机数列,只能通过算法得到一个伪随机数序列,那在编程当中说到的随机数,基本都是指伪随机数。
2. rand() 函数
2.1 函数说明
在linux下可以使用man 3 rand命令查看该函数的帮助手册。
/* 需包含的头文件 */
#include <stdlib.h>
/* 函数声明 */
int rand(void);【函数说明】该函数用于获取一个随机数,多次调用可以得到一组随机数序列。
【函数参数】none
【返回值】int类型,返回一个介于0到RAND_MAX(包含)之间的值,也就是闭区间上的[0, RAND_MAX]。我在Ubuntu 21.04的64位版本上试了一下,这个RAND_MAX值是2147483647。
【使用格式】一般情况下基本使用格式如下:
/* 需要包含的头文件 */
#include <stdlib.h>
/* 至少应该有的语句 */
int a;
a = rand();【注意事项】
(1)调用rand()可以得到[0, RAND_MAX]之间的伪随机数,多次调用rand()便可以生成一组伪随机数序列,但是需要注意,就是每一次运行程序所得到的随机数序列都是相同的。
(2)这里需要提到一个叫做种子的概念,rand()函数通过种子生成随机数序列,当种子相同时,生成的随机数是相同的,当我们没有使用设置中子的函数(srand())时,也就是说如果没有提供种子值,rand()函数将自动以1作为种子值,所以每次程序运行产生的随机数序列都是一样的。
2.2 使用实例
#include <stdio.h>
#include <stdlib.h>
int main(int arc, char *argv[])
{
int i = 0;
/* 打印随机数序列 */
printf("[");
for (i = 0; i < 8; i++)
{
printf("%d", rand() % 100);
if (i != 8 - 1)
printf(", ");
}
printf("]\n");
return 0;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,终端会有以下信息显示:
[83, 86, 77, 15, 93, 35, 86, 92]我们多运行几次,就会发现,产生的随机数永远都是这几个,也就是每个程序每次运行的时候得到的随机数都是一样的。
3. srand() 函数
3.1 函数说明
在linux下可以使用man 3 srand命令查看该函数的帮助手册。
/* 需包含的头文件 */
#include <stdlib.h>
/* 函数声明 */
void srand(unsigned int seed);【函数说明】该函数并不是用于生成随机数,srand()函数将其参数设置为rand()返回的伪随机整数新序列的种子。通过使用相同的种子值调用srand(),也可以得到相同的伪随机数序列。
【函数参数】
seed:unsigned int类型,作为产生随机数的种子,一般参数会设置为日历时间,就是通过time()函数获取的秒数,这样可以保证每次程序的运行所得到的的随机数序列不同。
【返回值】none
【使用格式】一般情况下基本使用格式如下:
/* 需要包含的头文件 */
#include <stdlib.h>
#include <time.h>
/* 至少应该有的语句 */
srand(time(NULL));【注意事项】该函数需要与与rand()一起使用。
3.2 使用实例
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int arc, char *argv[])
{
int i = 0;
/* 打印随机数序列 */
srand(time(NULL));
printf("[");
for (i = 0; i < 8; i++)
{
printf("%d", rand() % 100);
if (i != 8 - 1)
printf(", ");
}
printf("]\n");
return 0;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,多运行几次,会发现产生的随机数序列是不同的了:

4. rand_r() 函数
4.1 函数说明
在linux下可以使用man 3 rand_r命令查看该函数的帮助手册。
/* 需包含的头文件 */
#include <stdlib.h>
/* 函数声明 */
int rand_r(unsigned int *seedp);【函数说明】该函数也用于生成随机数,与rand()不同的是,它自带种子参数。
【函数参数】
seedp:unsigned int类型的指针变量,用于在调用之间存储状态,说实话,有点不理解这句话。在man手册中有说,如果rand_r()被调用时带有seedp指向的整数的相同初始值,并且在调用之间不修改该值,那么将产生相同的伪随机序列。当这个值改变的时候,产生的随机序列也会发生变化。
【返回值】int类型,返回一个介于0到RAND_MAX(包含)之间的值,也就是闭区间上的[0, RAND_MAX]。
【使用格式】一般情况下基本使用格式如下:
/* 需要包含的头文件 */
#include <time.h>
/* 至少应该有的语句 */
int a;
unsigned int b = 1;
a = rand_r(&b);【注意事项】
(1)该函数与rand()一样,每一次运行程序所得到的随机数序列都是相同的,想要每次产生不同的随机序列,我们可以使用日历时间作为随机数产生的种子,因为时间是不断变化的,所以每次启动程序,都会有不一样的种子,这也就意味着得到的随机序列也是不同的。
(2)seedp的值,在一次调用之后似乎会自己变化,需要重新赋值,至少我自己尝试的时候是有这样的情况产生,无法将这个值++或者--。
4.2 使用实例1
下边的这个实例,每次程序启动产生的随机序列都会与上一次一样。
#include <stdio.h>
#include <stdlib.h>
int main(int arc, char *argv[])
{
int i = 0;
int j = 0;
unsigned int num = 0;
/* 打印随机数序列 */
for(j = 0; j < 5; j++)
{
num = j;
if(j > 3) num = 0;
printf("j = %d,num = %d[", j, num);
for (i = 0; i < 8; i++)
{
printf("%d", rand_r(&num) % 100);
if (i != 8 - 1)
printf(", ");
}
printf("]\n");
}
return 0;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,多运行几次,会发现产生的随机数序列是相同的:

4.3 使用实例2
下边的这个实例,每次程序启动产生的随机序列都会与上一次不同。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int arc, char *argv[])
{
int i = 0;
unsigned int tm;
tm = (unsigned int)time(NULL);
/* 打印随机数序列 */
printf("[");
for (i = 0; i < 8; i++)
{
printf("%d", rand_r(&tm) % 100);
if (i != 8 - 1)
printf(", ");
}
printf("]\n");
return 0;
}在终端执行以下命令编译程序:
gcc test.c -Wall # 生成可执行文件 a.out
./a.out # 执行可执行程序然后,终端会有以下信息显示:
