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=2n1,其中 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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…