7.2 随机数与简单模拟

本篇学习 `rand`、`srand`、随机种子和简单取值范围映射,并能写出基础随机模拟程序。

随机数与简单模拟

概念说明

在实际编程中,我们经常需要生成随机数,例如掷骰子、随机抽样、洗牌、小游戏事件触发等。 在 C 语言里,最常见的入门接口是 <stdlib.h> 中的 rand()srand()

不过要先建立一个重要认识: rand() 生成的通常不是“真正随机数”,而是伪随机数,也就是由某个初始种子按固定规则推导出来的数列。

这意味着两件事:

  • 给定相同种子,通常会得到相同序列。
  • 如果你从不设置种子,程序每次启动时往往会重复同一条序列。

语法/规则

  1. rand() 会返回一个位于 0RAND_MAX 之间的整数。
  2. srand(seed) 用来设置随机种子,常见写法是 srand((unsigned)time(NULL));
  3. 种子通常只需要在程序启动时设置一次,不要在循环里反复重设。
  4. rand() % n 能快速得到 0n - 1 之间的整数,但会存在一定偏差。
  5. 对于入门练习和简单小游戏,rand() 足够用;对于密码学或安全用途,它远远不够。
  6. 如果要得到 16 之间的整数,常见写法是 rand() % 6 + 1
  7. 写随机逻辑时,最好先验证结果是否落在预期范围内,再考虑分布是否均匀。

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int range_ok = 1;

    srand(1);
    for (int i = 0; i < 100; i++) {
        int dice = rand() % 6 + 1;
        if (dice < 1 || dice > 6) {
            range_ok = 0;
        }
    }

    printf("range_ok = %d\n", range_ok);
    return 0;
}

输出结果:

1
range_ok = 1

这里使用固定种子 1,是为了让示例更稳定。 真正做随机模拟时,通常会改成基于时间的种子。

常见错误

  1. 每次生成随机数前都调用一次 srand,结果让序列反而变得更差。
  2. 忘记设置种子,导致程序每次启动都得到相同的随机序列。
  3. 以为 rand() 适合做密码、令牌或安全随机用途,实际上它并不适合。
  4. 只会写 rand() % n,却没意识到这种映射在严格场景下可能有偏差。
  5. 只关注“看起来随机”,却没有先验证结果是否满足基本范围约束。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字