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

C語言隨機數生成完全指南:srand/rand 機制、種子選擇、常見誤區與最佳實踐

     編輯:關於C語言

C語言隨機數生成完全指南:srand/rand 機制、種子選擇、常見誤區與最佳實踐

rand()/srand() 是 C 標準庫提供的偽隨機數生成器。本文深入剖析其運作機制、種子決定隨機序列、RAND_MAX 限制、線程不安全、現代替代方案,助你正確使用隨機數。

核心機制

  • rand() 返回 0 ~ RAND_MAX (標準保證 ≥ 32767,通常為 2147483647)
  • srand(seed) 設定初始種子,**相同種子產生完全相同序列**
  • 未呼叫 srand 等同 srand(1) (C99 標準)
  • 內部狀態為全域靜態變數,**非線程安全**

種子選擇策略

// 最常用:當前時間 (秒級)
srand((unsigned)time(NULL)); // 需 #include 

// 進階:時間 + 進程 ID + 線程 ID (減少碰撞)
srand((unsigned)(time(NULL) ^ getpid() ^ pthread_self()));

// 高品質:讀取 /dev/urandom (Linux) 或 CryptGenRandom (Windows)
unsigned int seed;
FILE *f = fopen("/dev/urandom", "rb");
fread(&seed, sizeof(seed), 1, f);
fclose(f);
srand(seed);

常見誤區與修正

誤區後果修正
迴圈內重複呼叫 srand(time(NULL))同一秒內產生相同序列程式啟動時**只呼叫一次**
用 rand() % N 產生 0~N-1分布不均 (模數偏差)用拒絕採樣或浮點縮放
以為 rand() 是真隨機加密用途極度不安全加密請用 /dev/urandom, getrandom(), arc4random()
多線程共用 rand()資料競爭,序列混亂用 rand_r(&seed) (POSIX) 或 C++11 <random>
假設 RAND_MAX = 32767移植到 64 位系統可能錯誤始終使用 RAND_MAX 宏

產生指定範圍整數的正確姿勢

// [0, n) 均勻分布 (拒絕採樣法)
int rand_range(int n) {
    if (n <= 0) return 0;
    int limit = RAND_MAX - RAND_MAX % n;
    int r;
    do { r = rand(); } while (r >= limit);
    return r % n;
}

// [min, max] 含邊界
int rand_int(int min, int max) {
    return min + rand_range(max - min + 1);
}

現代替代方案

  • C++11 <random>:std::mt19937 (梅森旋轉) + std::uniform_int_distribution,高品質、類型安全、可序列化
  • POSIX rand_r:線程安全版 rand,需自行管理種子
  • Linux getrandom():系統熵池直接讀取,適合加密
  • xoshiro256** / PCG:現代高速高品質演算法,適合模擬/遊戲

完整示範程式

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
    srand((unsigned)time(NULL)); // 僅一次!
    for (int i = 0; i < 10; i++)
        printf("%d ", rand() % 100 + 1); // 1~100 (教學用,實際用上述拒絕採樣)
    putchar('\n');
    return 0;
}

理解 srand/rand 的本質與限制,並在適當場合升級到現代隨機數庫,是編寫正確、高效、安全程式的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved