这是一个在 C 语言编程中非常常见但又容易引起混淆的函数,我会从以下几个方面为你彻底讲清楚:

- 核心概念:伪随机数
random()函数详解- 更推荐的标准库函数:
rand()和srand() - 如何生成指定范围的随机数
- 完整代码示例
- 总结与最佳实践
核心概念:伪随机数
你需要理解计算机生成的“随机数”并不是真正随机的,它们是通过一个确定的数学算法计算出来的序列,这个序列看起来是随机的,但其实是可预测的,我们称之为 伪随机数。
这个算法从一个初始值开始,这个初始值被称为 “种子”,如果每次运行程序时都使用相同的种子,那么生成的伪随机数序列也会是完全相同的。
举个例子: 想象一个食谱(算法),它需要一个“起始食材”(种子),如果你每次都用 1 个鸡蛋作为起始食材,做出来的蛋糕(随机数序列)都会一模一样,只有换一个起始食材(2 个鸡蛋),做出来的蛋糕才会不同。
random() 函数详解
random() 函数是 C 语言的一个函数,但它 不属于标准 C 库,它源自早期的 BSD Unix 系统,因此在很多现代编译器(如 GCC 在 Linux 上)中,你需要包含 <stdlib.h> 并且可能需要额外的编译选项才能使用。

-
函数原型:
long random(void);
-
功能: 返回一个
long类型的伪随机整数。 -
范围: 返回的值范围在不同的系统上可能不同,但通常是
0到RAND_MAX之间。RAND_MAX是一个在<stdlib.h>中定义的宏,它的值至少是 32767 (2^15 - 1)。 -
关键问题:种子
random()函数在程序启动时会自动初始化一个默认的种子。这意味着,如果你不手动设置种子,每次运行程序时,它生成的随机数序列都会是相同的!
(图片来源网络,侵删) -
设置种子:
srandom()为了解决种子问题,random()函数通常与srandom()函数配对使用。- 函数原型:
void srandom(unsigned int seed); - 功能: 用来设置
random()函数的种子。 - 最佳实践: 通常使用当前时间作为种子,因为每次运行程序时时间都不同,可以使用
time(0)函数(需要包含<time.h>)来获取当前时间。
- 函数原型:
更推荐的标准库函数:rand() 和 srand()
由于 random() 不是标准 C 函数,为了保证你的代码具有良好的 可移植性(可以在任何支持 C 语言的编译器上编译和运行),强烈推荐使用标准 C 库提供的 rand() 和 srand() 函数。
它们的工作方式与 random() 和 srandom() 完全相同,但它们是 ANSI C 标准的一部分,因此更通用、更安全。
-
函数原型:
int rand(void); void srand(unsigned int seed);
-
功能:
rand(): 生成一个int类型的伪随机整数。srand(): 设置rand()函数的种子。
-
范围:
rand()返回的值在0到RAND_MAX之间。RAND_MAX同样在<stdlib.h>中定义。
总结对比:
| 特性 | random() / srandom() |
rand() / srand() |
推荐度 |
|---|---|---|---|
| 标准性 | 非标准 (源自 BSD) | 标准 C (ANSI C) | ⭐⭐⭐⭐⭐ (强烈推荐) |
| 可移植性 | 差,依赖操作系统 | 极佳,所有编译器都支持 | ⭐⭐⭐⭐⭐ (强烈推荐) |
| 返回类型 | long |
int |
rand() 更常见 |
| 配套函数 | srandom() |
srand() |
功能相同 |
如何生成指定范围的随机数
无论是 random() 还是 rand(),它们默认生成的都是 0 到 RAND_MAX 之间的数,我们通常需要的是某个特定范围内的随机数,1 到 100。
常用方法(取模法):
使用取模运算符 可以很方便地实现。
公式:
random_number = (rand() % (max - min + 1)) + min;
rand() % N会生成一个0到N-1之间的数。rand() % (max - min + 1)会生成一个0到(max - min)之间的数。+ min将这个范围整体平移,最终得到min到max之间的数。
⚠️ 重要提醒:模运算的偏倚问题
当 RAND_MAX 不是 (max - min + 1) 的整数倍时,这种方法会导致结果分布不均匀,如果 RAND_MAX 是 32767,你想生成 1 到 100 的数,1 到 67 出现的概率会比 68 到 100 稍微高一点。
对于大多数非高精度的应用场景,这种偏倚可以忽略不计,如果需要完美的均匀分布,需要更复杂的算法,但 rand() % range 是最简单、最常用的方法。
完整代码示例
下面我们用 标准、推荐的 rand() 和 srand() 来写一个完整的例子。
目标:
- 初始化随机数种子(使用当前时间)。
- 生成并打印 10 个 1 到 100 范围内的随机整数。
- 生成并打印 5 个 0 到 9 范围内的随机整数。
#include <stdio.h>
#include <stdlib.h> // 包含 rand(), srand(), RAND_MAX
#include <time.h> // 包含 time()
int main() {
// 1. 设置随机数种子
// time(0) 返回自 1970 年 1 月 1 日以来的秒数。
// 将其作为种子,确保每次运行程序时种子都不同。
srand((unsigned int)time(0));
printf("--- 生成 1 到 100 的随机数 ---\n");
// 2. 生成 10 个 1 到 100 的随机数
for (int i = 0; i < 10; i++) {
// 使用公式: (rand() % (max - min + 1)) + min
int random_num = (rand() % 100) + 1;
printf("第 %d 个随机数: %d\n", i + 1, random_num);
}
printf("\n--- 生成 0 到 9 的随机数 ---\n");
// 3. 生成 5 个 0 到 9 的随机数
for (int i = 0; i < 5; i++) {
// 使用公式: (rand() % (max - min + 1)) + min
int random_num = (rand() % 10) + 0;
// 也可以简化为: int random_num = rand() % 10;
printf("第 %d 个随机数: %d\n", i + 1, random_num);
}
return 0;
}
如何编译和运行 (在 Linux/macOS 上使用 GCC):
gcc your_program_name.c -o random_test ./random_test
可能的一次运行结果:
--- 生成 1 到 100 的随机数 ---
第 1 个随机数: 42
第 2 个随机数: 18
第 3 个随机数: 77
第 4 个随机数: 53
第 5 个随机数: 91
第 6 个随机数: 4
第 7 个随机数: 66
第 8 个随机数: 29
第 9 个随机数: 50
第 10 个随机数: 33
--- 生成 0 到 9 的随机数 ---
第 1 个随机数: 7
第 2 个随机数: 0
第 3 个随机数: 9
第 4 个随机数: 2
第 5 个随机数: 5
再次运行,结果会完全不同。
总结与最佳实践
-
优先使用标准库:为了代码的可移植性,始终优先使用
rand()和srand(),而不是random()和srandom()。 -
必须设置种子:
rand()默认使用固定的种子,导致每次运行结果相同。务必在程序开始时调用srand((unsigned int)time(0))来设置基于时间的种子。 -
包含正确的头文件:使用
rand()和srand()时,记得包含<stdlib.h>;使用time(0)时,记得包含<time.h>。 -
掌握生成范围的方法:牢记公式
(rand() % (max - min + 1)) + min来生成指定范围的随机整数。 -
了解局限性:
rand()生成的随机数质量(随机性)并不高,不适合用于加密、高精度的科学模拟等场景,如果需要高质量的随机数,可以考虑使用 C++ 的<random>库或 C11 标准引入的arc4random等更高级的随机数生成器,但对于游戏、简单的模拟、抽奖程序等,rand()完全够用。
