C++ 之 伪随机数生成 <random>
C++ 标准库提供了生成随机和伪随机数的类。这些类包括:
- 随机数生成类:生成均匀分布整数序列的伪随机数生成器,包括随机数引擎、随机数引擎适配器以及预定义随机数生成器。
- 随机数分布类:将生成器生成的数字序列转换为遵循特定随机变量分布(如均匀分布、正态或泊松分布)的数字序列的对象。
随机数引擎
随机数引擎可以以种子数据为熵源生成伪随机数。
随机种子:初始化随机数生成器,然后利用算法不停迭代产生随机数。最简单的使用方式便是将其作为第一个随机数产生下一个随机数。
类模板 | 作用 |
---|---|
linear_congruential_engine | 实现线性同余算法 |
mersenne_twister_engine | 实现梅森缠绕器算法 |
subtract_with_carry_engine | 实现带进位减(一种延迟斐波那契)算法 |
其中线性同余引擎一般地快,并对状态的存储要求非常小。延迟斐波那契生成器在无先进算术指令集的处理器上非常快,但状态存储较为庞大,有时有不太想要的谱特性。梅森缠绕器较慢且拥有较大的状态存储要求,但只要有正确的参数,就会有最长的的不可重复序列,且拥有最想要的谱特性
这里介绍一下线性同余引擎和梅森缠绕器的详细实现过程。
线性同余算法
线性同余算法的实现较为简单,数学表达如下:
X n + 1 = mod ( ( a ∗ X n + b ) , c ) X_{n+1} = \text{mod} \left(\left(a*X_n+b\right), c\right) Xn+1=mod((a∗Xn+b),c)
但是其参数 a,b,c
需要满足一定条件,这里给出网上的一种C++代码实现如下:
static uint32 prngState = 0;
uint32 init_rand(uint32 seed)
{//Seed the pseudo-random number generatorprngState += seed;
//Successful processingreturn SUCCESS;
}
uint32 _rand(void)
{uint32 value;
//Use a linear congruential generator (LCG) to update the state of the PRNGprngState *= 1103515245;prngState += 12345;value = (prngState >> 16) & 0x07FF;
prngState *= 1103515245;prngState += 12345;value <<= 10;value |= (prngState >> 16) & 0x03FF;
prngState *= 1103515245;prngState += 12345;value <<= 10;value |= (prngState >> 16) & 0x03FF;
//Return the random valuereturn value;
}int32 rand_range(int32 min, int32 max)
{int32 value;
//Valid parameters?if (max > min){//Pick up a random value in the given rangevalue = min + (_rand() % (max - min + 1));}else{//Use default valuevalue = min;}
//Return the random valuereturn value;
}
该代码摘自知乎博文
梅森缠绕器
梅森缠绕器的实现过程较为复杂
- 第一阶段:初始化,根据随机种子获得初始的梅森旋转链;
- 第二阶段:根据已有梅森旋转链进行旋转算法获取下一次循环的旋转链;
- 第三阶段:根据梅森旋转链计算随机数;
其C++代码实现如下:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <time.h>using namespace std;bool isInit;
int index;
int MT[624]; //624 * 32 - 31 = 19937void srand(int seed)
{index = 0;isInit = 1;MT[0] = seed;for(int i=1; i<624; i++){int t = 1812433253 * (MT[i-1] ^ (MT[i-1] >> 30)) + i;MT[i] = t & 0xffffffff; //取最后的32位}
}void generate()
{for(int i=0; i<624; i++){// 2^31 = 0x80000000// 2^31-1 = 0x7fffffffint y = (MT[i] & 0x80000000) + (MT[(i+1) % 624] & 0x7fffffff);MT[i] = MT[(i + 397) % 624] ^ (y >> 1);if (y & 1)MT[i] ^= 2567483615;}
}
int rand()
{if(!isInit)srand((int)time(NULL));if(index == 0)generate();int y = MT[index];y = y ^ (y >> 11);y = y ^ ((y << 7) & 2636928640);y = y ^ ((y << 15) & 4022730752);y = y ^ (y >> 18);index = (index + 1) % 624;return y; //y即为产生的随机数
}int main()
{srand(0); //设置随机种子int cnt = 0;for(int i=0; i<1000000; i++) //下面的循环是用来判断随机数的奇偶概率的 {if(rand() & 1)cnt++;}cout<<cnt / 10000.0<<"%"<<endl;return 0;
}
该代码摘自it610网,该博文包含原理解析。
随机数引擎适配器
随机数引擎适配器生成以另一随机数引擎为熵源的伪随机数,以随机数引擎为基础产生过更为多样性的随机序列。
类模板 | 作用 |
---|---|
discard_block_engine | 舍弃随机数引擎的某些输出 |
independent_bits_engine | 将一个随机数引擎的输出打包为指定位数的块 |
shuffle_order_engine | 以不同顺序发送一个随机数引擎的输出 |
预定义随机数生成器
如果有需要可以根据上述的随机数引擎和随机数引擎适配器构建属于自己的随机数生成器。同时C++的标准库也提供了需要经典的随机数生成器如下:
类型 | 定义 |
---|---|
minstd_rand0 |
std::linear_congruential_engine<std::uint_fast32_t, 16807, 0, 2147483647> 由 Lewis、Goodman 及 Miller 发现于 1969,由 Park 与 Miller 于 1988 采纳为“最小标准” |
minstd_rand |
std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> 较新的“最小标准”,为 Park、 Miller 及 Stockmeyer 于 1993 推荐 |
mt19937 |
std::mersenne_twister_engine<std::uint_fast32_t, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253> 32 位梅森缠绕器,由松本与西村设计于 1998 |
mt19937_64 |
std::mersenne_twister_engine<std::uint_fast64_t, 64, 312, 156, 31, 0xb5026f5aa96619e9, 29, 0x5555555555555555, 17, 0x71d67fffeda60000, 37, 0xfff7eee000000000, 43, 6364136223846793005> 64 位梅森缠绕器,由松本与西村设计于 2000 |
ranlux24_base | std::subtract_with_carry_engine<std::uint_fast32_t, 24, 10, 24> |
ranlux48_base | std::subtract_with_carry_engine<std::uint_fast64_t, 48, 5, 12> |
ranlux24 |
std::discard_block_engine<std::ranlux24_base, 223, 23> 24 位 RANLUX 生成器,由 Martin Lüscher 与 Fred James 设计于 1994 |
ranlux48 |
std::discard_block_engine<std::ranlux48_base, 389, 11> 48 位 RANLUX 生成器,由 Martin Lüscher 与 Fred James 设计于 1994 |
knuth_b | std::shuffle_order_engine<std::minstd_rand0, 256> |
default_random_engine | 实现定义 |
随机数分布
处理随机数生成器的输出,以使得输出结果按照定义的统计概率密度函数进行分布。
均匀分布 | |
---|---|
uniform_int_distribution | 产生在一个范围上均匀分布的整数值 |
uniform_real_distribution | 产生在一个范围上均匀分布的实数值 |
伯努利分布 | |
---|---|
bernoulli_distribution | 产生伯努利分布上的 bool 值 |
binomial_distribution | 产生二项分布上的整数值 |
negative_binomial_distribution | 产生负二项分布上的整数值 |
geometric_distribution | 产生几何分布上的整数值 |
泊松分布 | |
---|---|
poisson_distribution | 产生泊松分布上的整数值 |
exponential_distribution | 产生指数分布上的实数值 |
gamma_distribution | 产生 |
weibull_distribution | 产生威布尔分布上的实数值 |
extreme_value_distribution | 产生极值分布上的实数值 |
正态分布 | |
---|---|
normal_distribution | 产生标准正态(高斯)分布上的实数值 |
lognormal_distribution | 产生对数正态分布上的实数值 |
chi_squared_distribution产生 | χ2 |
cauchy_distribution | 产生柯西分布上的实数值 |
fisher_f_distribution | 产生费舍尔 |
student_t_distribution | 产生学生 |
采样分布 | |
---|---|
discrete_distribution | 产生离散分布上的随机整数 |
piecewise_constant_distribution | 产生分布在常子区间上的实数值 |
piecewise_linear_distribution | 产生分布在定义的子区间上的实数值 |
其他工具
std::uniform_random_bit_generator
:均匀随机位生成器是函数对象,它返回无符号整数值,并使得每个值在可能结果的范围中拥有(理想上)相等的被返回概率。
std::random_device
:使用硬件熵源的非确定随机数生成器
std::generate_canonical
: 使通过随机数生成器获得的数据均匀分布在 [0, 1) 上
seed_seq
:通用的偏差消除的混淆种子序列生成器,通过提高种子的多样性降低随机序列的重复出现
C++ 之 伪随机数生成 <random>相关推荐
- (SEED-Lab) 伪随机数生成实验
(SEED-Lab) 伪随机数生成实验 欢迎大家访问我的GitHub博客 https://lunan0320.cn 文章目录 (SEED-Lab) 伪随机数生成实验 一.实验目的 二.实验步骤与结果 ...
- 一个伪随机数生成算法
一个伪随机数生成算法 这几天逛程序员论坛,发现了不少好帖子,增长了不少知识,现拿其中一则为例说明. 某人提出一个问题,说怎么样能生成一亿个不重复的随机数呢? 问题表述起来很简单,似乎只要弄明白什么叫随 ...
- 【Python 标准库学习】伪随机数生成库 — random
欢迎加入 Python 官方文档翻译团队:https://www.transifex.com/python-doc/ 随机函数在很多科学计算中都会用到,比如生成一系列随机数来计算平均值.高斯分布.伽马 ...
- 分享一种高效伪随机数生成算法
我们知道C语言提供了随机数生成,另外Qt也提供了随机数的生成. 比如C语言,生成0-19随机数,如下: srand(time(nullptr)); // 从1970-01-01 00:00:00到现在 ...
- python伪随机数模块random详解
本文已整合到这里:Python内置数学模块全整理,易查易阅 文章目录 基本原理 整数和字节 分布函数 用于序列的随机函数 基本原理 用于生成伪随机数,之所以有个伪字,是因为计算机没法生成真正的随机数. ...
- Python伪随机数模块random
random模块 该模块实现了各种分布的伪随机数生成器.(包括在实数轴上计算均匀.正态(高斯).对数正态.负指数.伽马和贝塔分布的函数)不应将此模块的伪随机生成器用于安全目的.有关安全性或加密用途,请 ...
- 随机数种子与伪随机数生成原理
总之: 1.伪随机数并不是假随机数,这里的"伪"是有规律的意思,就是计算机产生的伪随机数既是随机的又是有规律的. 2.随机种子来自系统时钟,确切地说,是来自计算机主板上的定时/计数 ...
- 伪随机数生成器——random模块的用法
1. 使用random.random(),生成区间 [0,1)内的浮点数 import random for i in range(3):a = random.random()print(" ...
- 随笔记录——numpy4(伪随机数生成)
numpy.random模块填补了Python内建的random模块的不足,可以高效地生成多种概率分布下的完整样本值数组. 22.指定均值方差,生成符合正态分布的随机数 np.random.norma ...
最新文章
- 批处理下的 cd 与 cd /d 命令
- “被狗啃”的按钮引发的开源社区信任危机
- 联想平板刷机机器人_消费终端年出货量破1.2亿,杨元庆:联想是智能化转型的赋能者...
- 【性能测试】性能测试工具选择
- 介绍Node assert, should.js, mocha, Karma, Travis CI
- Win32汇编——内存映射文件
- 华为OJ-奥运会排行榜C++
- JAVA中读写文件操作
- 2018-2019-1 20165318 20165322 20165326 实验二 固件程序设计
- python中round(x、2)是什么意思_python中round函数具体使用详解
- 整理:X86架构图示以及各部分解释
- 【Materials Studio学习六】构建固液表面
- 爬虫逆向 js逆向常用工具简单介绍
- 记录从指尖悄悄流逝的时间
- mixly编程怎样音乐_使用mixly和Arduino结合蜂鸣器播放音乐
- SQL PLUS命令使用大全(转,特有用)
- sublime text 3搭建Python3的开发环境
- 如何用python编程能实现输入诗句的上句显示下句_Python爬虫之诗歌接龙
- X264代码走读二(intra_refresh实现)
- 24核48线虚拟化服务器,24核48线程的威力:戴尔PowerEdge R910服务器评测