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

C 語言隨機數生成實戰大全:從基礎 rand/srand 到進階洗牌與非標準函數辨析

     編輯:關於C語言

核心認知:偽隨機數的決定性本質

C 標準庫 rand() 生成的是偽隨機數。它以種子為初始值,透過線性同餘法等遞推公式產生序列。序列週期極長時統計特性近似隨機。預設種子為 1,導致程式每次執行輸出相同。必須用 srand() 設定種子打破確定性。

標準組合拳:srand() + rand()

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

srand((unsigned)time(NULL)); // 以當前時間為種子
int r = rand();              // 0 ~ RAND_MAX (>=32767)

關鍵點:srand 僅需呼叫一次,通常在 main 開頭。重複呼叫 srand 且種子相同會重置序列。

範圍映射:三種常見需求的標準寫法

目標範圍推薦代碼原理
[0, 1) 浮點數rand() / (RAND_MAX + 1.0)浮點除法歸一化
[min, max] 整數min + rand() % (max - min + 1)模運算,分布略有偏差
嚴格均勻整數拒絕採樣循環丟棄超出完整區間的值

非標準函數:random()、randomize() 為什麼不用?

  • random(num):直接返回 [0, num-1],方便但非 ANSI C,僅限舊版 Borland/Turbo C。
  • randomize():自動以時間設種子,同樣非標準。
  • 結論:跨平台、標準合規專案嚴禁使用,堅持 rand/srand。

進階技巧:生成不重複隨機序列(洗牌演算法)

需求:從 1~N 產生不重複隨機排列(如撲克牌洗牌、抽獎)。

// Fisher-Yates 洗牌:O(N) 時間、O(N) 空間
int a[N+1];
for (int i = 1; i <= N; ++i) a[i] = i;
for (int i = N; i >= 1; --i)
    swap(&a[i], &a[rand() % i + 1]); // +1 關鍵:避免索引 0
// a[1]~a[N] 即為隨機排列

另一種「檢查法」效率極低(O(N²) 甚至無限循環),生產環境禁止使用。

常見錯誤與避坑指南

  1. 忘記 srand():每次運行結果相同。
  2. 循環中重複 srand(time(NULL)):若循環極快,種子相同導致產生相同數。
  3. 用 char 接收 rand():rand() 返回 int,char 會截斷高位。
  4. 模運算偏差:RAND_MAX+1 不整除範圍大小導致分布不均,高精度場景用浮點縮放或拒絕採樣。
  5. 多執行緒競爭:rand() 非執行緒安全,C++11 應用 <random> 庫(mt19937 + 分佈器)。

現代 C++ 替代方案:<random> 標準庫

#include <random>
std::mt19937 gen(std::random_device{}());
std::uniform_int_distribution<> dist(1, 100);
int r = dist(gen); // 高質量、執行緒安全、分布完美

C++11 起強烈建議棄用 rand/srand,改用 <random> 體系。

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