【C标准库】C语言随机数生成函数:详解rand()与srand()函数


🌈个人主页:聆风吟_
🔥系列专栏:C语言标准库
🔖少年有梦不应止于心动,更要付诸行动。


文章目录

  • 📋前言
  • [一. rand()函数:生成伪随机数](#一. rand()函数:生成伪随机数)
    • [1.1 头文件](#1.1 头文件)
    • [1.2 函数原型](#1.2 函数原型)
    • [1.3 函数功能](#1.3 函数功能)
    • [1.4 返回值](#1.4 返回值)
    • [1.5 用法](#1.5 用法)
    • [1.6 问题:为什么每次运行结果相同?](#1.6 问题:为什么每次运行结果相同?)
  • [二. srand()函数:设置随机数种子](#二. srand()函数:设置随机数种子)
    • [2.1 头文件](#2.1 头文件)
    • [2.2 函数原型](#2.2 函数原型)
    • [2.3 函数功能](#2.3 函数功能)
    • [2.4 辅助函数time()说明](#2.4 辅助函数time()说明)
    • [2.5 常用种子设置方法](#2.5 常用种子设置方法)
    • [2.6 注意事项](#2.6 注意事项)
  • 📝全文总结

📋前言

rand()函数是C/C++中用于生成伪随机数的标准库函数,其底层基于线性同余法实现,生成的随机数序列受 "种子(seed)" 控制。默认情况下,rand()的种子固定为 1,因此每次运行程序生成的随机数序列完全相同;配合srand()函数设置动态种子,可让随机数序列具备真正的 "随机性"。


一. rand()函数:生成伪随机数

1.1 头文件

cpp 复制代码
// C标准库
#include <stdlib.h>

1.2 函数原型

cpp 复制代码
int rand(void);

1.3 函数功能

rand()函数是用来生成一个伪随机数。

1.4 返回值

返回值是一个介于 0 ~ RAND_ MAX (32767) 之间的伪随机整数。

RAND_MAX 值的查询方法:
RAND_MAX是标准库定义的宏,表示rand()函数能返回的最大值,大多数视线中默认值为 32767,不同编译器可能略有差异。

验证方法(VS编译器):

  • 方法一:转到RAND_MAX定义查看:
  • 方法二:使用代码验证:
c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("当前编译器的 RAND_MAX = %d\n", RAND_MAX);
    return 0;
}

运行结果示例:

c 复制代码
当前编译器的 RAND_MAX = 32767

1.5 用法

rand() 默认生成的范围过大,实际开发中我们通常需要指定范围(如 1~100),核心技巧是取模运算 + 偏移量

(1)原理说明:

  • 取模运算 n % m 的结果范围是 0 ~ m-1
  • 加上偏移量可调整起始值,例如 n % m + k 可将范围调整为 k ~ m+k-1

(2)通用公式:

c 复制代码
// 生成[min, max]范围内的随机整数
int random_num = rand() % (max - min + 1) + min;
// 公式拆解:
// 1. rand() % (max - min + 1) → 生成 0 ~ (max-min) 的整数
// 2. + min → 将范围偏移为 min ~ max

(3)更多示例:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    // 示例1:生成0-59的随机数
    int b1 = rand() % 60;

    // 示例2:生成1-60的随机数
    int b2 = rand() % 60 + 1;

    // 示例3:生成1994-2023的随机数
    int b3 = rand() % 30 + 1994;

    // 示例4:生成-10到10的随机数
    int b4 = rand() % 21 - 10;

    printf("b1 (0-59): %d\n", b1);
    printf("b2 (1-60): %d\n", b2);
    printf("b3 (1994-2023): %d\n", b3);
    printf("b4 (-10-10): %d\n", b4);

    return 0;
}

1.6 问题:为什么每次运行结果相同?

(1)问题现象:

直接运行下面的示例代码,你会发现:每次启动程序,生成的随机数序列完全相同。

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int ret = rand();

    // 输出结果:每次运行都是相同的序列
    printf("%d\n", ret);

    return 0;
}

(2)原因分析:

这是因为rand()函数生成的伪随机数,由一个隐藏的全局种子变量(seed)控制。在调用rand()函数前,程序会先检查是否主动调用过srand(seed)为伪随机数生成器设置种子:

  • 如果调用过,伪随机数生成器会以你设定的种子值作为初始值;
  • 如果未主动调用srand(seed),系统会在首次调用rand()时自动执行一次 srand(1),即把全局种子变量的初始值固定为 1。
  • 由于伪随机数是通过固定算法基于种子值生成的,只要种子值相同,每次调用 rand() 产生的伪随机数序列就完全一致。

而我们的代码中没有主动调用srand设定种子,系统每次都会用默认的种子 1 初始化,因此每次运行程序得到的随机数结果都是相同的。

(3)解决方案:

若想让程序每次运行生成的随机数序列都不重复,核心是让每次初始化伪随机数生成器时使用的种子值唯一。我们可以将系统当前时间作为种子:

c 复制代码
srand((unsigned int)time(NULL));

由于程序每次运行的时间戳必然不同,以此初始化的种子值也会唯一,基于固定算法生成的伪随机数序列自然就不会重复了。


二. srand()函数:设置随机数种子

2.1 头文件

cpp 复制代码
#include <stdlib.h>

2.2 函数原型

cpp 复制代码
void srand (unsigned int seed);

2.3 函数功能

srand()用于设置rand()函数的随机数生成器的种子值。通过提供不同的种子,可以生成不同的随机数序列。

2.4 辅助函数time()说明

(1)头文件和函数原型:

c 复制代码
// 头文件
#include <time.h>
// 函数原型
// time_t 是整型别名(通常为 long/unsigned int),用于存储时间戳
time_t time(time_t *tloc);

(2)函数功能:

返回从 "1970 年 1 月 1 日 00:00:00" 到当前时间的秒数(时间戳);

(3)参数:

通常使用time(NULL)time(0)获取当前时间

2.5 常用种子设置方法

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    // 第一步:设置种子为当前系统时间(仅需调用1次,建议放在程序开头)
    srand((unsigned int)time(NULL));

    // 第二步:生成10个1~100的随机数
    printf("生成10个1~100的随机数:\n");
    for (int i = 0; i < 10; i++)
    {
        int random_num = rand() % 100 + 1;
        printf("%d ", random_num);
    }
    printf("\n");

    return 0;
}

代码剖析:

c 复制代码
// 设置种子为当前系统时间
srand((unsigned int)time(NULL));

因为srand函数需要接受的是unsigned int类型的值,而time返回的是time_t类型的值,所以在传参的时候要使用强制类型转换。

运行结果示例(每次运行不同):

2.6 注意事项

  1. srand()一般只需在程序的开头调用一次 ,无需在每次调用rand()前重复调用;

  2. 若短时间内重复运行程序(如 1 秒内),时间戳相同,仍可能生成相同序列(可结合毫秒级时间优化,新手暂无需掌握);

  3. rand()生成的是 "伪随机数",并非密码学安全的随机数(加密场景需用专用库)。


📝全文总结

本文关键要点回顾:

  1. rand()函数 :生成0 ~ RAND_MAX之间的伪随机整数
  2. srand()函数:设置随机数种子,确保每次运行产生不同序列
  3. 范围控制:通过取模运算生成指定范围的随机数
  4. 常用模式srand((unsigned int)time(NULL))配合rand()
cpp 复制代码
// 标准使用模式
#include <stdlib.h>
#include <time.h>

int main()
{
    // 1. 初始化种子(程序开始处调用一次)
    srand((unsigned int)time(NULL));
    
    // 2. 生成指定范围的随机数
    int random_num = rand() % (max - min + 1) + min;
    
    return 0;
}

今天的干货分享到这里就结束啦!如果觉得文章还可以的话,希望能给个三连支持一下,聆风吟的主页还有很多有趣的文章,欢迎小伙伴们前去点评,您的支持就是作者前进的最大动力!

相关推荐
松涛和鸣1 小时前
DAY56 ARM Cortex-A Bare Metal
linux·服务器·c语言·开发语言·arm开发·数据库
计算机网恋2 小时前
Ubuntu中VSCode配置CC++环境
c语言·vscode·ubuntu
Once_day2 小时前
CC++八股文之内存泄漏
c语言·c++
Yupureki2 小时前
《算法竞赛从入门到国奖》算法基础:入门篇-贪心算法(下)
c语言·c++·学习·算法·贪心算法
项目題供诗2 小时前
C语言基础(六)
c语言·开发语言
Remember_9932 小时前
【数据结构】初识 Java 集合框架:概念、价值与底层原理
java·c语言·开发语言·数据结构·c++·算法·游戏
小乔的编程内容分享站2 小时前
C语言结构体相关笔记
c语言·笔记
项目題供诗4 小时前
C语言基础(七)
c语言·开发语言
方圆工作室13 小时前
【C语言图形学】用*号绘制完美圆的三种算法详解与实现【AI】
c语言·开发语言·算法