隨機數是模擬、遊戲、加密、統計採樣的基石。本文系統梳理 C 語言傳統 rand/srand 機制的核心原理、常見誤區、正確用法,並對比 C++11 <random> 現代標準庫的優勢,助你根據場景選擇最佳方案。
| 函數/宏 | 聲明 | 作用 | 關鍵點 |
|---|---|---|---|
RAND_MAX | 宏常量(≥32767) | rand() 最大返回值 | 實現相關,通常為 32767 (2^15-1) |
rand() | int rand(void) | 生成偽隨機整數 [0, RAND_MAX] | 線性同餘生成器,周期有限 |
srand() | void srand(unsigned seed) | 設置種子 | 同種子 → 同序列,可重現性關鍵 |
#include <stdlib.h>
#include <time.h>
int main() {
srand((unsigned)time(NULL)); // 以當前時間作種子
for (int i = 0; i < 10; i++) {
printf("%6d\n", rand());
}
return 0;
}
設計哲學解析: C 標準庫刻意不將時間種子內建於 rand(),原因包括:
// 錯誤!導致分佈不均 int x = rand() % 100; // 0-99,但低數值概率略高
原因: RAND_MAX+1 通常不能被 100 整除,導致前 (RAND_MAX+1) % 100 個數值多出一次機會。
// 生成 [0, n) 均勻分佈整數
int uniform_int(int n) {
return (int)(n * rand() / (RAND_MAX + 1.0));
}
// 生成 [a, b] 閉區間整數
int uniform_range(int a, int b) {
return a + (int)((b - a + 1) * rand() / (RAND_MAX + 1.0));
}
原理: 將 [0, RAND_MAX] 映射到 [0, 1) 實數區間,再線性縮放,數學期望均勻。
// [0.0, 1.0)
double rand_double() {
return rand() / (RAND_MAX + 1.0);
}
// [a, b)
double rand_double_range(double a, double b) {
return a + (b - a) * rand_double();
}
<random> 現代標準庫(強烈推薦)C 風格 rand 存在周期短、低位隨機性差、線程不安全、分佈控制弱等缺陷。C++11 提供專業級設施:
#include <random>
#include <iostream>
int main() {
// 1. 隨機引擎(梅森旋轉 MT19937,周期 2^19937-1)
std::mt19937 eng(std::random_device{}()); // 硬件熵源播種
// 2. 分佈器
std::uniform_int_distribution dist_int(0, 99); // [0,99] 整數
std::uniform_real_distribution dist_real(0, 1); // [0,1) 實數
std::normal_distribution dist_norm(0, 1); // 正態分佈 μ=0,σ=1
// 3. 使用
for (int i = 0; i < 5; i++) {
std::cout << dist_int(eng) << ' '
<< dist_real(eng) << ' '
<< dist_norm(eng) << '\n';
}
// 線程安全:每線程一引擎實例
// 可序列化:保存/恢復引擎狀態
return 0;
}
| 引擎 | 周期 | 速度 | 質量 | 適用場景 |
|---|---|---|---|---|
minstd_rand | 2^31 | 快 | 一般 | 嵌入式、輕量級 |
mt19937 | 2^19937-1 | 中 | 優 | 通用首選 |
mt19937_64 | 2^19937-1 | 中 | 優 | 需 64 位輸出 |
ranlux24 | 10^171 | 慢 | 極高 | 科學計算、蒙特卡洛 |
<random>,除非嚴格受限於 C89/C99 環境std::random_device(硬件熵)> time(nullptr) > 固定常量/dev/urandom、CryptGenRandom、BCryptGenRandom),不可用偽隨機隨機數質量直接關繫系統安全性、模擬準確性與測試可靠性。拋棄 rand()%N 這類「民間偏方」,擁抱標準庫的數學嚴謹性,是專業開發者的基本素養。