rand() / srand() 是 C 標準庫提供的偽隨機數生成器(PRNG)。理解其確定性序列本質與種子機制,是正確使用的關鍵。本文系統整理調用規則、常見誤區、範圍映射公式與浮點擴展技巧。
| 函數 | 原型 | 說明 |
|---|---|---|
rand() | int rand(void) | 返回 [0, RAND_MAX] 間偽隨機整數,RAND_MAX ≥ 32767 (0x7FFF) |
srand() | void srand(unsigned seed) | 設定種子,初始化內部狀態。同種子 → 同序列。 |
rand() 前若未調用 srand(),隱性執行 srand(1)。srand(seed),後續 rand() 依該種子產生確定序列。for (int i=0; i<10; i++) printf("%d ", rand()%6);
每次運行輸出完全相同:5 5 4 4 5 4 0 0 4 2。適合除錯、測試、可重現實驗。
srand(6);
for (int i=0; i<10; i++) printf("%d ", rand()%6);
輸出:4 1 5 1 4 3 4 4 2 2。同樣可重現,但序列不同。
#include <stdlib.h>
#include <time.h>
srand((unsigned)time(0)); // 秒級時間戳作種子
for (int i=0; i<10; i++) printf("%d ", rand()%6);
每秒啟動程式種子不同 → 序列不同。注意:同一秒內多次啟動種子相同,高頻場景需結合 getpid()、clock() 或高精度計時器。
// 產生 [a, b) 區間整數(含 a,不含 b)
int r = (rand() % (b - a)) + a;
// 簡寫:[0, n)
int r = rand() % n;
原理: 取模將 0~RAND_MAX 映射至 0~n-1。若 RAND_MAX+1 不能被 n 整除,分布略有偏差(對大多數應用可忽略)。
// [0.0, 1.0)
double r = rand() / (double)RAND_MAX;
// [0.0, 10.0)
double r = rand() / (double)(RAND_MAX / 10.0);
// 通用 [min, max)
double r = min + (max - min) * rand() / (double)RAND_MAX;
關鍵:除以 RAND_MAX(轉 double),而非取模。取模僅適用整數均勻分布。
| 需求 | 推薦方案 |
|---|---|
| 密碼學安全 | /dev/urandom、getrandom()、arc4random() |
| 高品質統計特性 | C11 random.h、Mersenne Twister (mt19937)、PCG |
| 執行緒安全 | rand_r(&seed) (POSIX)、C11 thrd_local 狀態 |
| 可重現並行 | Jump-ahead / 分塊種子策略 |
rand(),改用現代 PRNG。