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

C/C++ 隨機數生成完全指南:從 rand() 到現代最佳實踐

     編輯:關於C++

引言

隨機數在模擬、遊戲、加密、測試等領域不可或缺。C/C++ 提供了 rand()/srand() 這對經典函數,但其隨機品質與易用性在現代標準下已顯不足。本文系統梳理傳統用法的陷阱,並介紹 C++11 <random> 標準庫的現代解決方案。

傳統 rand()/srand() 機制與陷阱

基本運作原理

  • rand() 返回 0 到 RAND_MAX(至少 32767)之間的偽隨機整數。
  • 預設種子為 1,導致每次程式啟動產生相同序列——利於除錯,不利於實際應用。
  • srand(seed) 設定種子;相同種子產生相同序列。

常見錯誤與修正

現代 C++11 <random> 最佳實踐

標準庫提供「隨機數引擎」+「分布器」的組合設計,分離隨機來源與統計分布,支援高品質、執行緒安全、可移植的隨機數生成。

核心組件

  • 引擎:std::mt19937(梅森旋轉,推薦通用)、std::random_device(非決定性熵源,用於播種)。
  • 分布器:uniform_int_distribution、uniform_real_distribution、normal_distribution 等,保證統計特性。

標準範例:產生 [min, max] 區間均勻整數

#include <random>
#include <iostream>

int main() {
    std::random_device rd;                 // 硬體熵源
    std::mt19937 gen(rd());                // 引擎播種
    std::uniform_int_distribution<> dis(1, 100); // 閉區間 [1,100]

    for (int i = 0; i < 10; ++i)
        std::cout << dis(gen) << ' ';
}

進階技巧

  • 執行緒區域儲存:thread_local std::mt19937 gen(std::random_device{}()); 避免鎖競爭。
  • 可重現除錯:測試時用固定種子 std::mt19937 gen(42);。
  • 浮點數區間:std::uniform_real_distribution<double> dis(0.0, 1.0); 產生 [0,1)。
  • 正態分布:std::normal_distribution<> dis(mean, stddev);。

遷移建議

  1. 新專案直接使用 <random>,勿再碰 rand()。
  2. 舊代碼維護期可保留 rand(),但新增功能改用現代設施。
  3. 加密級隨機數需用作業系統 API(/dev/urandom、CryptGenRandom、std::random_device 視實作而定)。

總結

rand() 時代已過,C++11 <random> 以「引擎+分布」架構解決了品質、偏差、執行緒安全、可移植性等全方位問題。掌握 std::mt19937 + uniform_int_distribution 組合,即可覆蓋 95% 以上的應用場景,寫出專業級的隨機數代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤寫法問題正確做法
重複呼叫 srand(time(NULL))若在迴圈內呼叫,同一秒內種子相同,產生重複數列程式啟動時 僅呼叫一次 srand((unsigned)time(nullptr))
直接用 rand() % N模數偏差:當 RAND_MAX 不可被 N 整除時,分布不均使用拒絕採樣或改用 <random> 分布器
多執行緒共用 rand()非執行緒安全,內部狀態競爭各執行緒使用獨立引擎實例(C++11)