首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言隨機數生成完全指南:rand/srand、種子策略、範圍映射、執行緒安全與現代替代方案

     編輯:關於C語言

標準庫函數 (``)


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)));

範圍映射:生成 [min, max] 區間整數


// 錯誤寫法: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 / C11)


// 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++ 專案首選

C 語言手寫 PCG32 (單檔案、無依賴、高品質)


// 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);

總結建議

  1. **教學/簡單測試/可復現除錯**:`srand(time(NULL))` + `rand()` + 拒絕採樣映射。
  2. **多執行緒**:`rand_r` (POSIX) 或 TLS 種子 + 自定義生成器 (xorshift/PCG)。
  3. **高性能模擬/遊戲**:PCG / Xoshiro256** / Mersenne Twister (C 移植版)。
  4. **安全敏感 (密鑰、Token)**:**絕對禁止 `rand()`**,必須用 OS CSPRNG (`getrandom`, `BCryptGenRandom`, `/dev/urandom`)。
  5. **C++ 專案**:直接用 `` (`std::mt19937` + `std::uniform_int_distribution`)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved