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

C語言隨機數生成詳解:從 rand/srand 到偽隨機本質與最佳實踐

     編輯:關於C語言

核心函數與頭文件

#include    // rand, srand, RAND_MAX
#include      // time (用於種子)

int rand(void);           // 返回 0 ~ RAND_MAX 間偽隨機數
void srand(unsigned int seed);  // 設置種子

RAND_MAX 至少 32767(15 位)。

基本用法

1. 指定範圍整數

[0, N)      : rand() % N
[a, b)      : rand() % (b - a) + a
[a, b] 閉區間: rand() % (b - a + 1) + a

2. 浮點數 [0, 1)

double r = rand() / (double)RAND_MAX;

3. 種子初始化(關鍵!)

srand((unsigned)time(NULL));  // 當前時間作種子,每次運行結果不同

若不調用 srand,默認等同 srand(1),每次運行產生相同序列。

偽隨機數本質深度解析

為什麼叫「偽」隨機?

  • 計算機按確定性算法(線性同餘法等)從種子計算序列。
  • 同種子、同算法、同平台 → 完全相同序列。
  • 「偽」指:統計特性接近隨機,但本質確定、可重現。

種子來源

  • 早期 DOS:讀取 BIOS 定時器計數器(端口 0x40:0x6C),毫秒級變化。
  • 現代 OS:time(NULL) 秒級時間,或 /dev/urandom、CryptGenRandom 等熵源。

線性同餘法(LCG)示例

// 典型參數(ANSI C / glibc 等各異)
seed = (seed * 1103515245 + 12345) % (1u << 31);
return (int)(seed >> 16) & 0x7FFF;

常見陷阱與最佳實踐

錯誤做法後果正確做法
循環中反覆 srand(time(NULL))若循環極快,種子相同 → 產生相同數程序啟動時 僅調用一次 srand
用 rand()%N 產生大範圍數低位隨機性差,分布不均用浮點縮放或更好算法(C++11 )
多線程共用 rand()非線程安全,序列交織混亂用 thread_local 引擎或 C++11
加密場景用 rand()可預測,極不安全用 /dev/urandom、CryptGenRandom、std::random_device

現代 C++ 推薦: 库

#include 
#include 

std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
// 均勻整數 [a, b]
std::uniform_int_distribution dist(a, b);
int r = dist(rng);
// 均勻浮點 [0, 1)
std::uniform_real_distribution distf(0.0, 1.0);
double rf = distf(rng);

優點:週期極長(2^19937-1)、統計特性優、線程安全、分布靈活。

總結

  1. srand 全程只調用一次,種子用高精度時間或熵源。
  2. 簡單場合用 rand()%,嚴謹場合用 C++11 。
  3. 加密/安全場景禁用 rand 族函數。
  4. 理解偽隨機本質:可重現性是特性(利於測試),非缺陷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved