標準庫 `rand()` 通常實現為:next = (next * 1103515245 + 12345) % 2^31 (GLIBC) 或類似參數。特點:
rand() % N 導致分佈不均 (模數偏差)。#include <stdlib.h>
#include <time.h>
#include <stdint.h>
// 1. 種子只設一次,用高熵源
void init_rand() {
uint64_t seed = 0;
FILE *ur = fopen("/dev/urandom", "rb");
if (ur) { fread(&seed, 1, sizeof(seed), ur); fclose(ur); }
else { seed = (uint64_t)time(NULL) ^ (uintptr_t)&seed; }
srand((unsigned)seed);
}
// 2. 均勻分佈 [0, n-1] (拒絕採樣消除模數偏差)
int rand_uniform(int n) {
if (n <= 0) return 0;
const int limit = RAND_MAX - (RAND_MAX % n);
int r;
do { r = rand(); } while (r >= limit);
return r % n;
}
// 3. 浮點 [0.0, 1.0)
double rand_double() {
return (double)rand() / (RAND_MAX + 1.0);
}
| 方案 | 標準/庫 | 特點 | 適用場景 |
|---|---|---|---|
| C11 ` | 自實現 / PCG | 無狀態、執行緒局部、統計質量優、速度極快、種子 128 位 | 高效能模擬、遊戲、非密碼學 |
| C++11 ` | STL | 引擎 (mt19937) + 分佈 (uniform_int_distribution) 分離、型別安全 | C++ 專案首選 |
| POSIX `random()` / `drand48()` | BSD/System V | 比 `rand()` 好,但仍非密碼學級 | 舊 Unix 代碼遷移 |
| `getrandom()` / `/dev/urandom` / `CryptGenRandom` / `BCryptGenRandom` | OS 內核 | 密碼學級真隨機 (熵池)、慢、阻塞 (getrandom flags 控制) | 金鑰生成、Nonce、Session ID、密碼重設 Token |
| 硬體指令 `RDRAND` / `RDSEED` (x86) / `RNDR` (ARMv8.5) | CPU | 硬體熵源、極快、需檢查 CF/標誌位 | 高吞吐密碼學隨機 |