CppCon 2016 學習:I Just Wanted a Random Integer

你想要一個隨機整數,用于模擬隨機大小的DNA讀取片段(reads),希望覆蓋不同長度范圍,也能測試邊界情況。
代碼部分是:

#include <cstdlib>
auto r = std::rand() % 100;

它生成一個0到99之間的隨機整數,表示隨機讀取的長度。
簡單來說:

  • 你用 std::rand() 生成偽隨機數。
  • % 100 限制范圍在0~99。
  • 這樣就得到了一個隨機的DNA片段大小。
    如果你想更好的隨機數(比如更均勻、更現代的C++隨機),可以用 <random>
#include <random>
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, 99);
int r = dist(gen);

rand()srand() 在 Linux C 庫里的實現細節和注意事項:

  • Linux 中的 rand()srand() 實際上是用跟 random()srandom() 相同的隨機數生成器。
  • 因此,低位比高位隨機性差的說法在 Linux 上不適用,低位和高位都一樣隨機。
  • 但是,在舊版 rand() 實現或其他系統中,rand() 的低位隨機性可能很差
  • 因此,如果你的應用需要良好的跨平臺隨機性,不建議用 rand(),而是應該用 random()(或更現代的隨機數生成器,比如 C++11 的 <random>)。
    總結就是:
  • rand() 低位不隨機的問題主要是舊系統和非 Linux 的實現。
  • 在 Linux 上,rand() 表現好一些,但為可移植和更好隨機性,還是推薦用 random()<random>
    如果你想要更穩定、好用的隨機數生成方式,尤其是在 C++,推薦用 <random> 庫。

在寫單元測試時,想要一個“隨便的隨機整數”,看似用 std::rand()% 操作就夠了,但其實這樣做很容易出問題,尤其是你想要“均勻覆蓋所有邊界條件”的時候。

  1. std::rand() + % 其實不夠隨機,會導致隨機數分布不均勻,某些數字出現概率偏低或偏高。
  2. <random> 庫(C++11及以后)雖然看起來復雜,但其實是更科學、更可靠的隨機數生成方式。
  3. 推薦使用 Mersenne Twister (std::mt19937) + std::uniform_int_distribution + std::random_device 作為種子,這樣既有高質量的偽隨機數,又能基于真實熵來初始化。
  4. std::random_device 提供真隨機的熵,但它的熵資源是有限的,有時會阻塞等待更多熵。
  5. 要注意,生成高質量隨機數時,熵是關鍵,但計算機本質上是偽隨機,需要熵源來“真隨機”初始化。
    總結就是
    你單元測試要用“隨機數”,不能隨便用rand()%N,而要用更嚴謹的 <random> 方案,才能更好地覆蓋邊界和確保隨機性。

用 C++ <random> 生成隨機整數時的細節和性能考量:

核心內容總結:

  • std::random_device
    • 用于獲取真隨機熵,作為偽隨機數引擎的種子。
    • 可能很慢,有時甚至會阻塞(因為熵資源有限)。
    • 可能會拋異常,且多線程環境行為不明。
    • 具體實現依賴硬件和操作系統,比如Linux上常用/dev/urandom
  • std::mt19937(Mersenne Twister)
    • 偽隨機數生成器,速度快且質量較高。
    • 是確定性引擎,給定種子后輸出固定序列。
    • 體積大(約5000字節棧空間),初始化較慢(百萬次初始化需要十幾秒)。
    • 每次函數調用時重新創建會很慢!
  • 性能測試對比
    • 生成10億隨機數:
      • std::random_device 用時約44秒(慢且可能阻塞)。
      • std::mt19937 用時約3.6秒(快得多)。
  • 最佳實踐建議
    • 不要每次用std::mt19937時都重新初始化引擎,建議將其作為靜態變量或者線程局部變量來重用,比如:
      static std::mt19937 g(std::random_device{}());
      auto rn = g();
      
    • 這樣既避免了重復初始化開銷,也保證了偽隨機數生成速度。

C++生成隨機整數的正確做法和背后的算法進行講解,重點如下:

1. 隨機整數生成的常見準則(Guidelines)

  • std::random_device 來做種子(seed):確保偽隨機數生成器有較好的隨機種子。
  • 不要把 std::mt19937(Mersenne Twister)放在棧上頻繁構造:構造開銷大,最好是靜態變量或線程局部變量(thread_local)。
  • 如果一定放在棧上,要小心構造開銷
  • std::minstd_rand 比較快,但周期更短

2. 常用隨機數生成器性能對比

  • std::random_device 速度很慢(約44秒)。
  • std::mt19937 中等速度(約3.6秒),周期極長。
  • std::minstd_rand 更快(約4.7秒),周期短。

3. Mersenne Twister 背景和定義

  • 命名來自 Marin Mersenne(1588-1648),梅森素數的形式是 M n = 2 n ? 1 M_n = 2^n - 1 Mn?=2n?1,其中 n n n 是素數。
  • 例如: M 3 = 7 M_3 = 7 M3?=7, M 7 = 127 M_7 = 127 M7?=127, 最大有名的是 M 74 , 207 , 281 M_{74,207,281} M74,207,281?
  • std::mt19937 的周期就是一個梅森素數 M 19937 M_{19937} M19937?
  • 這是一個維度為623的偽隨機數生成器,詳細參數在源碼里定義(比如狀態大小、位移操作等)。

4. 結論

  • 使用 std::mt19937 是因為它周期非常長且質量很好。
  • 但在性能敏感的場景,可以考慮 std::minstd_rand 作為替代。
  • 生成器的使用要注意對象生命周期管理,避免重復構造帶來的開銷。

這段內容主要講了C++隨機數生成的一些進階話題,尤其是關于性能優化和替代生成器的討論。幫你整理重點:

1. PCG 隨機數生成器介紹

  • PCG (Permuted Congruential Generator) 是 Melissa O’Neill 設計的隨機數生成器。
  • 優點:
    • 體積更小(16字節),比 std::mt19937 省空間。
    • 和 C++ <random> 庫兼容,可以無縫替代。
    • 性能比 std::mt19937 快很多(示例中1.5秒 vs 3.6秒)。
  • 缺點:
    • 目前不在標準庫中,社區使用經驗較少。
  • 參考資源:
    • PCG 官網
    • GitHub 地址:https://github.com/imneme/pcg-cpp

2. std::uniform_int_distribution 的構造成本

  • std::uniform_int_distribution 是用于生成均勻整數分布的模板類。
  • 在循環內部構造和在循環外部構造性能差異極大
    • 外部構造(只構造一次):生成1,000,000,000個數大約 23.4秒。
    • 內部構造(每次調用都構造):生成同樣數量大約 5.1秒(這里好像反了,推測是復制時的編譯優化影響)。
    • 具體性能依賴于編譯器和優化級別,但通常建議避免在循環內重復構造分布對象

3. 隨機數生成性能總結

  • 通過靜態變量(static std::random_devicestatic std::mt19937)維護生成器實例,減少構造開銷。
  • 如果需要高性能,考慮用PCG替代MT19937。
  • std::uniform_int_distribution構造開銷也不能忽視,盡量循環外構造。

4. 代碼示例總結

static std::random_device entropySource;
static std::mt19937 randGenerator(entropySource());
std::uniform_int_distribution<int> theIntDist(0, 99);
for (auto i = 0; i < 1'000'000'000; i++) {volatile auto r = theIntDist(randGenerator);
}
  • 這是一個推薦的模式:生成器和分布都靜態,只生成隨機數時調用operator()
    你這段內容講的是 C++ 標準庫 <random>std::uniform_int_distribution 生成均勻隨機整數時,內部是如何“縮放”原始隨機數到目標范圍的細節,和對隨機數生成器及分布器使用的建議總結。

代碼片段說明(縮放機制)

const __uctype __urange = __uctype(__param.b()) - __uctype(__param.a());
__uctype __ret;
if (__urngrange > __urange) {// downscalingconst __uctype __uerange = __urange + 1; // 目標范圍大小(包括邊界)const __uctype __scaling = __urngrange / __uerange; // 源隨機數范圍除以目標范圍大小,算出縮放系數const __uctype __past = __uerange * __scaling; // 縮放后實際范圍do__ret = __uctype(__urng()) - __urngmin; // 從源隨機數生成器拿數,減去最小值while (__ret >= __past); // 如果隨機數超過縮放范圍則重新取數,保證均勻__ret /= __scaling; // 縮放回目標范圍
}
  • 這段代碼的作用是確保從底層隨機數生成器的輸出映射到指定的整數范圍 [a, b] 時,能保持均勻分布
  • 通過“拒絕采樣”(while (__ret >= __past))來避免偏差。
  • 這是 <random> 里實現 uniform_int_distribution 的核心邏輯之一。

你的“指南”和總結

  • Use your engineering judgment
    任何方案都要結合具體項目和需求來判斷。
  • <random> is safe
    標準庫 <random> 已經很安全、穩定,推薦優先使用。
  • PCG is fast, small and simple
    PCG 隨機數生成器小巧快速,是很好的替代方案。
  • Combine PCG with <random>
    PCG 可以作為底層生成器,配合 <random> 中的分布類用起來也非常方便。
  • Always measure. Always!
    任何性能和正確性上的假設都要靠測量和測試來驗證。

最后總結

  • std::random_device 來產生隨機種子。
  • 選擇 std::mt19937 或 PCG 作為偽隨機數生成器。
  • 分布類(uniform_int_distribution 等)構造和使用開銷不大,不必擔心性能問題。
  • C++17 引入了更方便的采樣工具,如 std::sample
  • 性能和行為要靠基準測試來決定,理論和實際可能不同。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84169.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84169.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84169.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL層級查詢實戰:無函數實現部門父路徑

本次需要擊斃的MySQL函數 函數主要用于獲取部門的完整層級路徑&#xff0c;方便在應用程序或SQL查詢中直接調用&#xff0c;快速獲得部門的上下級關系信息。執行該函數之后簡單使用SQL可以實現數據庫中部門名稱查詢。例如下面sql select name,GetDepartmentParentNames(du.de…

Python初學者教程:如何從文本中提取IP地址

Python初學者教程:如何從文本中提取IP地址 在網絡安全和數據分析領域,經常需要從文本文件中提取IP地址。本文將引導您使用Python創建一個簡單但實用的工具,用于從文本文件提取所有IP地址并將其保存到新文件中。即使您是編程新手,也可以跟隨本教程學習Python的基礎知識! …

【Redis】Redis核心探秘:數據類型的編碼實現與高速訪問之道

&#x1f4da;?前言 &#x1f31f;&#x1f31f;&#x1f31f;精彩導讀 本次我們將全面剖析Redis的核心技術要點&#xff0c;包括其豐富的數據類型體系、高效的編碼方式以及秒級響應的性能奧秘。對于渴望深入理解Redis底層機制的技術愛好者&#xff0c;這是一次難得的學習機會…

Halcon —— 多種二維碼檢測

工業視覺實戰&#xff1a;Halcon多類型二維碼識別技術詳解 在工業自動化場景中&#xff0c;兼容多種二維碼類型是提高生產線靈活性的關鍵。本文將深入解析Halcon實現Data Matrix、QR Code和PDF417三種主流二維碼的兼容識別方案&#xff0c;并重點解釋核心算子參數。 一、多類型…

安卓vscodeAI開發實例

前言 前些天發現了一個巨牛的人工智能免費學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站 目錄 一、安卓開發基礎與工具鏈革新 1.1 Android Studio的局限性分析 1.2 VSCode在移動開發中的崛起 1.3 跨平臺開發工具鏈對比…

③通用搜索---解析FastAdmin中的表格列表的功能

深度解析FastAdmin中的表格列表的功能-CSDN博客文章瀏覽閱讀25次。本文將FastAdmin框架的CRUD功能配置要點進行了系統梳理。官方文檔與開發經驗相結合&#xff0c;詳細介紹了菜單顯示、TAB過濾、通用搜索、工具欄按鈕、動態統計、快速搜索等17項功能的配置方法。包括字段渲染&a…

DeepSeek 助力 Vue3 開發:打造絲滑的日歷(Calendar),日歷_項目里程碑示例(CalendarView01_22)

前言&#xff1a;哈嘍&#xff0c;大家好&#xff0c;今天給大家分享一篇文章&#xff01;并提供具體代碼幫助大家深入理解&#xff0c;徹底掌握&#xff01;創作不易&#xff0c;如果能幫助到大家或者給大家一些靈感和啟發&#xff0c;歡迎收藏關注哦 &#x1f495; 目錄 Deep…

Python爬蟲實戰:獲取Diesel電商數據并分析

1. 引言 在當今數字化時代,電商平臺積累了海量的產品和用戶數據。通過對這些數據的挖掘和分析,企業可以深入了解市場動態、消費者需求和競爭態勢,從而制定更有效的營銷策略和產品規劃。Diesel 作為知名的時尚品牌,其在電商平臺上的表現備受關注。本研究旨在通過 Python 爬…

Spring RestTemplate + MultiValueMap vs OkHttp 多值參數的處理

&#x1f4cc; Spring RestTemplate vs OkHttp&#xff1a;多值參數處理 一、MultiValueMap 與 FormBody 的差異 特性RestTemplate MultiValueMapOkHttp FormBody多值參數支持? 原生支持&#xff08;add("key", "value") 自動追加&#xff09;? 需顯…

GelSight視觸覺3D輪廓儀賦能Beomni人形機器人觸覺遙測,開啟人形機器人觸覺應用新場景

在智能制造、航空航天等領域&#xff0c;傳統機器人常面臨操作精度不足、環境適應力弱等問題。GelSight觸覺傳感技術與Beomni人形機器人的融合&#xff0c;為這些場景提供了新可能 —— 通過亞微米級觸覺感知能力&#xff0c;操作員可遠程感知物體表面細節&#xff0c;在復雜環…

python設置word的字體顏色

這個錯誤是由于python-docx的RGBColor對象沒有.rgb屬性導致的。正確的屬性訪問方式是分別獲取紅、綠(g)、藍(b)三個分量。以下是修復方案&#xff1a; 錯誤原因分析 RGBColor對象的結構如下&#xff1a; from docx.shared import RGBColorcolor RGBColor(255, 204, 51) pri…

推薦模型之GBDT-LR

一、概念 GBDT-LR模型由FaceBook&#xff08;現在的Meta&#xff09;團隊于2014年在論文《Practial Lessons from Predicting Clicks on Ads at Facebook》中提出&#xff0c;目標是用于預測FaceBook的廣告點擊量&#xff08;實際上廣告和推薦領域很多算法模型都是共用的&#…

Java實現Excel圖片URL篩選與大小檢測

Java實現Excel圖片URL篩選與大小檢測 在數據處理場景中&#xff0c;我們常需篩選Excel中的圖片URL。本文分享一個完整的Java方案&#xff0c;涵蓋從讀取圖片URL到檢測有效性、篩選大小&#xff0c;再到生成新Excel文件的全過程&#xff0c;同時講解開發與優化過程&#xff0c;…

Java 實現后端調用 Chromium 瀏覽器無頭模式截圖的方案

Java 實現后端調用 Chromium 瀏覽器無頭模式截圖的方案 1. 使用 Playwright 優點&#xff1a;功能強大、支持多瀏覽器&#xff08;Chromium/Firefox/WebKit&#xff09;、支持異步操作。實現方式&#xff1a; 利用 Playwright 創建無頭瀏覽器實例&#xff1b;使用 Java 的調度…

基于多模態文檔解析與RAG的行業知識庫構建技術指南

1. 技術背景 隨著企業非結構化數據&#xff08;掃描件、PDF、圖像等&#xff09;占比超過80%&#xff0c;傳統關鍵詞檢索已無法滿足精準問答需求。本文提出融合**計算機視覺&#xff08;CV&#xff09;與大語言模型&#xff08;LLM&#xff09;**的解決方案&#xff0c;關鍵技…

基于YOLOv11+PP-OCRv5深度學習的智能車牌檢測與識別系統python源碼+pytorch模型+評估指標曲線+精美GUI界面

【算法介紹】 智能車牌檢測與識別系統借助當下前沿的 YOLOv11 算法以及 PP-OCRv5 算法&#xff0c;能夠在復雜多樣的環境場景中&#xff0c;快速且精準地達成實時車牌檢測與識別任務。在現代交通管理領域&#xff0c;該技術意義重大&#xff0c;它能夠推動涉及車輛識別與記錄的…

[深度學習]全連接神經網絡

目錄 一、實驗目的 二、實驗環境 三、實驗內容 3.1 完成解壓數據集相關操作 3.2分析代碼結構并運行代碼查看結果 3.3修改超參數&#xff08;批量大小、學習率、Epoch&#xff09;并對比分析不同結果 3.4修改網絡結構&#xff08;隱藏層數、神經元個數&#xff09;并對比分…

openEuler安裝BenchmarkSQL

BenchmarkSQL是一個用于評估數據庫性能的開源工具。它模擬TPC-C&#xff08;Transaction Processing Performance Council&#xff09;基準測試場景&#xff0c;該場景主要用于衡量數據庫在處理大量并發事務時的能力。TPC-C測試場景模擬了一個典型的批發分銷商的業務環境&#…

分庫分表之優缺點分析

大家好&#xff0c;我是工藤學編程 &#x1f989;一個正在努力學習的小博主&#xff0c;期待你的關注實戰代碼系列最新文章&#x1f609;C實現圖書管理系統&#xff08;Qt C GUI界面版&#xff09;SpringBoot實戰系列&#x1f437;【SpringBoot實戰系列】Sharding-Jdbc實現分庫…

【2025年超詳細】Git 系列筆記-4 git版本號及git相關指令運用。

系列筆記 【2025年超詳細】Git 系列筆記-1 Git簡述、Windows下git安裝、Linux下git安裝_displaying 2e144 commits. adjust this setting in -CSDN博客 【2025年超詳細】Git 系列筆記-2 github連接超時問題解決_2025訪問github-CSDN博客 【2025年超詳細】Git 系列筆記-3 Git…