int rand(void); // 返回 0 ~ RAND_MAX (至少 32767) 偽隨機數
void srand(unsigned int seed); // 設定種子
核心特性:`rand()` 為**線性同餘生成器 (LCG)** 或類似演算法,**確定性序列**。同種子 → 同序列。**非執行緒安全** (全域狀態)。**統計品質差** (低位周期短),**不可用於密碼學**。
#include
#include
int main() {
srand(12345); // 固定種子
for (int i = 0; i < 5; i++) printf("%d ", rand());
return 0;
}
// 每次運行輸出相同序列
#include
srand((unsigned)time(NULL)); // 秒級精度
// 缺點:同一秒內多次啟動種子相同
// 改進:結合進程 ID、高精度時間
srand((unsigned)(time(NULL) ^ (getpid() << 16)));
// 錯誤寫法:rand() % (max-min+1) + min
// 缺陷:模運算引入統計偏差 (除非 RAND_MAX+1 能被範圍整除)
// 正確寫法:拒絕採樣
int rand_range(int min, int max) {
if (min > max) return min;
int range = max - min + 1;
int limit = RAND_MAX - (RAND_MAX % range); // 最大可接受值
int r;
do { r = rand(); } while (r >= limit); // 拒絕超出部分
return min + r % range;
}
// 浮點數 [0.0, 1.0)
double rand_double() {
return (double)rand() / (RAND_MAX + 1.0);
}
// [min, max) 浮點
double rand_double_range(double min, double max) {
return min + rand_double() * (max - min);
}
// POSIX: rand_r (需自行管理種子狀態)
unsigned int seed = time(NULL);
int r = rand_r(&seed); // 線程局部種子,安全
// C11: 無標準線程安全 rand。建議自行實現或用第三方庫。
// 簡易線程局部 LCG (xorshift32)
static __thread uint32_t tls_seed = 0;
uint32_t tl_rand() {
if (!tls_seed) tls_seed = (uint32_t)(time(NULL) ^ (uintptr_t)&tls_seed);
tls_seed ^= tls_seed << 13;
tls_seed ^= tls_seed >> 17;
tls_seed ^= tls_seed << 5;
return tls_seed;
}
| 方案 | 特點 | 適用場景 |
|---|---|---|
| Mersenne Twister (mt19937) | 週期 2^19937-1、統計優、速度快、C++ ` | 科學計算、模擬、遊戲 (非加密) |
| PCG (Permuted Congruential Generator) | 狀態小、速度極快、統計優、無狀態衝突 | 嵌入式、高性能、替代 rand |
| Xorshift / Xoshiro / Xoroshiro | 極簡實現、無乘法、通過 BigCrush | 極度資源受限、JIT、Shader |
| CryptGenRandom / `/dev/urandom` / `getrandom()` / `arc4random()` | 密碼學安全 (CSPRNG) | 金鑰生成、Token、Session ID、Nonce |
| C++11 ` | 引擎 + 分布 分離、類型安全、標準化 | C++ 專案首選 |
// pcg32.h / .c
typedef struct { uint64_t state; uint64_t inc; } pcg32_t;
void pcg32_seed(pcg32_t *rng, uint64_t initstate, uint64_t initseq) {
rng->state = 0; rng->inc = (initseq << 1) | 1;
pcg32_random(rng); rng->state += initstate; pcg32_random(rng);
}
uint32_t pcg32_random(pcg32_t *rng) {
uint64_t old = rng->state;
rng->state = old * 6364136223846793005ULL + rng->inc;
uint32_t xorshifted = (uint32_t)(((old >> 18u) ^ old) >> 27u);
uint32_t rot = (uint32_t)(old >> 59u);
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
// 使用: pcg32_t rng; pcg32_seed(&rng, time(NULL), getpid()); uint32_t r = pcg32_random(&rng);