首页 > 编程笔记 > C语言笔记

C语言随机数生成教程(超级详细)

在计算机编程中,随机数的生成是一个常见需求,无论是在游戏开发、模拟实验还是数据加密中,随机数都扮演着重要的角色。本文将深入探讨C语言中如何生成随机数,以及如何巧妙地设置随机数的范围,以满足不同的应用场景。

1. 随机数的生成

1) rand() 函数

C语言提供了⼀个函数叫 rand(),位于 stdlib.h 头文件中。这函数是可以生成随机数的,原型如下:

int rand (void);

rand() 函数会返回⼀个伪随机数,这个随机数的范围是在 0~RAND_MAX 之间,这个 RAND_MAX 的大小是依赖编译器上实现的,例如在 GCC 7.4 上是 2147483647。

下面我们可以测试⼀下 rand() 函数,利用循环产生 5 个随机数:
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("%d\n", rand());
    // 多次调用以展示随机性
    for (int i = 0; i < 5; i++) {
        printf("%d\n", rand());
    } 
    return 0;
}
多运行几次程序,就会发现一个奇怪的现象,就是每次运行的结果都一样。

第一次运行的结果:

1804289383
846930886
1681692777
1714636915
1957747793
424238335


第二次运行的结果:

1804289383
846930886
1681692777
1714636915
1957747793
424238335


我们会发现一次运行中产生的 5 个数字是相对随机的,下一次运行程序生成的结果会和上一次一模⼀样。

如果再深入了解⼀下,我们就不难发现,其实 rand() 函数生成的随机数是伪随数;伪随机数不是真正的随机数,是通过某种算法生成的随机数。真正的随机数的是无法预测下⼀个值是多少的。而 rand() 函数是对⼀个叫“种子”的基准值进行运算生成的随机数。

之所以前面每次运行程序产生物的随机数序列是⼀样的,那是因为 rand() 函数生成随机数的默认种子是 1。如果要生成不同的随机数,就要让种子是变化的。

2) srand() 函数

C语言中又提供了⼀个函数叫 srand(),用来初始化随机数的生成器的,srand() 的原型如下:

void srand (unsigned int seed);

seed 参数是无符号整数。

程序中在调用 rand() 函数之前先调用 srand() 函数,通过 srand() 函数的参数 seed 来设置 rand() 函数生成随机数的时候的种子,只要种子在变化,每次生成的随机数序列也就变化起来了。

那也就是说给 srand() 的种子是如果是随机的,rand() 就能生成随机数。

3) time() 函数

在程序中我们⼀般是使用程序运行的时间作为种子的,因为时间时刻在发生变化的。 在C语言中有⼀个函数叫 time() ,就可以获得这个时间,time() 函数原型如下:

time_t time (time_t* timer);

time() 函数会返回当前的日历时间,其实返回的是 1970 年 1 月 1 日 0 时 0 分 0 秒到现在程序运行时间之间的差值,单位是秒。返回的类型是 time_t 类型的,time_t 类型本质上其实就是 32 位或者 64 位的整型类型。

time函数返回的这个时间差也被叫做:时间戳。

参数说明:
time() 函数的时候需要包含头文件 time.h

如果只是让 time() 函数返回时间戳,可以这样写:

time(NULL);

调用time函数返回时间戳,这里没有接收返回值

把上面生成随机数的代码修改成下面这样:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    srand((unsigned int)time(NULL)); // 初始化随机数生成器
    for (int i = 0; i < 5; i++) {
        printf("%d\n", rand());
    }
    return 0;
}
多运行几次,会发现每次的结果就会有所差异。

第一次的运行结果:

806661939
622836408
1406112608
1857692088
766549693


第二次的运行结果:

515321644
198233088
1226779537
907305239
1774942676


srand() 函数通常是不需要频繁调用的,一次运行的程序中调用一次就够了。

2. 设置随机数的范围

在实际应用中,我们往往需要生成特定范围内的随机数。通过取模运算和数学计算,我们可以轻松实现这一需求。下面举几个例子。

生成 0~99 之间的随机数,方法如下:

rand() %100

余数的范围是 0~99。

生成 1~100 之间的随机数,方法如下:

rand()%100+1

%100 的余数是 0~ 99,0~ 99 的数字 +1,范围是 1~100。

生成 100~200 的随机数,方法如下:

100 + rand()%(200-100+1)

余数的范围是 0~ 100,加 100 后就是 100~200

综上所述,生成 a~b 范围的公式为:

a + rand()%(b-a+1)

3. 几点总结和说明

1) 如何确保生成的随机数具有真正的随机性?
答:通过将 time(NULL) 的返回值作为种子,我们可以在很大程度上保证每次程序执行时生成的随机数序列都是不可预测的。

2) 如果需要在特定的范围内生成随机数,应该如何操作?
答: 可以通过公式a + rand() % (b - a + 1)来实现在 [a, b] 区间内生成随机数。

3) 为什么不同编译器中的 RAND_MAX 值可能会有所不同?
答: RAND_MAX 的值由编译器的实现决定,不同的编译器可能会采用不同的数值上限,因此它的值在不同环境中可能会有所变化。

声明:《C语言系列教程》为本站“54笨鸟”官方原创,由国家机构和地方版权局所签发的权威证书所保护。