C++——随机数引擎和分布

2023-11-08

随机数引擎是一个函数对象类,他们定义了一个调用运算符,不接受任何参数并且返回一个unsigned整数。我们可以适用其生成随机数。

为什么称其为随机数引擎,因为我们通常不会直接适用引擎生成随机数,而是将其传入一个分布类对象中对齐进行分布生成,所以称其为引擎。

分布类型也是一个函数对象。定义了一个调用运算符,不接受任何参数,返回一个unsigned值

创建一个default_random_engine类的对象,即随机数引擎。标准库定义了许多的随机数引擎,他们性能和随机性质不同。每个编译器都会指定其中一个default_random_engine。此类型一般具有常用的性质。

int main()
{
    default_random_engine e;
    for(int i=0;i<10;++i)
    {
        cout << e() << ' ';
    }
    return 0;
}

运行结果

如果不改变种子,那么随机序列也不会该变。

生成特定分布的随机数那么就需要分布类了

uniform_int_distribution        均匀随机整型分布类

int main()
{
    default_random_engine e;
    uniform_int_distribution<unsigned > u(0,9);
    for(int i =0;i<10;++i)
    {
        cout << u(e) << ' ';
    }
    return 0;
}

运行结果

其中uniform_int_distribution<unsigned > u(0,9)

表示生成随机数的值是unsigned类型的,在0-9之间

在进行随机数生成的时候,将引擎传入进分布对象,生成符合分布的随机数。

分布类型

分布类型也是一个函数对象。定义了一个调用运算符,接受一个随机数引擎作为参数。分布类对象适用引擎生成的随机数,并将其映射到指定的分布。 

查看引擎的随机数产生范围

int main()
{
    default_random_engine e;
    cout << "max num is " << e.max() << endl << "min num is " << e.min();
    return 0;
}

运行结果

和c类似,如果不重新导入种子随机数引擎生成的随机数是固定的。

可以将对象定义为static的,这样再次调用函数对象后,会保持状态,返回接下来的随机数。

pair<unsigned,unsigned> get_unum()
{
    default_random_engine e;
    static default_random_engine static_e;
    int a = 0, b = 0;
    for(int i=0;i<10;++i)
    {
        a += e();
        b += static_e();
    }
    return {a,b};
}
int main()
{
    pair<unsigned, unsigned> p1;
    pair<unsigned, unsigned> p2;
    p1 = get_unum();
    p2 = get_unum();
    p1.first == p2.first ? cout << "equal" : cout << "not equal";
    cout << endl;
    p1.second == p2.second ? cout << "equal" : cout << "not equal";
    return 0;
}

 运行结果

 重置随机数引擎种子

    default_random_engine e;
    static default_random_engine static_e;
    static int flag = 1;
    if(flag == 2)   e.seed(114514);
    int a = 0, b = 0;

运行结果

当我们说随机数发生器,是指随机数引擎和分布对象的组合。

简单的来说,生成随机数并不是引擎或者分布类的单一责任,而是二者互相配合。

我们所需要的随机,是真正的随机,即随机数区间中的任何一个数被生成的概率都是相同的。C语言通常适用rand()函数来产生随机数,导入时间种子,这样做虽然相对随机,但其实并不是真正的随机。并且,再处理浮点数的时候会遇到一些看似正确的错误。

假设要写一个蒙特卡洛随机模拟实验,需要用到一个0-1之间的随机数。

C语言会这样写,实际上,我也确实是这样写的。

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

就实验结果来说,精准度确实比一些奇奇怪怪的方法要准确,可以说差强人意。那么缺陷在哪里呢。

因为随机整数相除后的精度下降。在C++ Primer里是这样说的

这正方法不正确的原因是随机整数的精度通常低于随机浮点数,这样,有一些浮点值就永远不会被生成。  

使用C++标准库,我们就会轻松的得到一些浮点值了。 

int main()
{
    default_random_engine e;
    uniform_real_distribution<double> u (0,1);
    for(int i=0;i<10;++i)
    {
        cout << u(e) << ' ';
    }
    return 0;
}

运行结果

有些分布类是有默认结果类型的

uniform_real_distribution<> u (0,1);

 这样和上述的的作用是一样的,因为这个分布类的默认结果为double类型。

有时候还会用到非均匀分布的随机数,像正态分布。标准库提供了这样的功能。实际上,标准库提供了20种分布类型。

适用正态分布类,生成正态分布的随机数并进行可视化操作

normal_distribution<>        正态分布

正态分布模板类,产生符合正态分布的浮点数,默认随机数类型为double。 

#include <iostream>
#include <random>
#include <vector>
#include <algorithm>
using namespace std;


int main()
{
    default_random_engine e;
    normal_distribution<> n(4,1.5); //均值是4 标准差是1.5
    vector<unsigned> vec(9);
    for(int i=0;i!=500;++i)
    {
        unsigned v = lround(n(e)); //舍入到最接近的整数
        if(v<vec.size())
            ++vec.at(v);
    }
    for_each(vec.begin(), vec.end(),[](unsigned  u){while(u--) cout << "*"; cout << endl;});
    return 0;
}

运行结果

 上面提到了分布类是模板类,但是,有一个分布类是例外。

bernoulli_distribution         伯努利分布

这个类也是非常的有意思,他返回一个bool值,默认情况下返回true的概率为0.5。

可以用它写出一些有意思的小玩应

#include <iostream>
#include <random>
using namespace std;


int main()
{
    const unsigned tot_num = 10;
    default_random_engine e;
    bernoulli_distribution b;
    cout << "欢迎来到鱿鱼游戏" << endl;
    char sel;
    bool flag;
    for(int i=0; i!=tot_num;++i)
    {
        flag = b(e);
        cout << "left or right (l/f): ";
        cin >> sel;
        if(flag == true && sel == 'l')
        {
            cout << "YOU DIED";
            exit(0);
        }
        else if(flag == false && sel == 'r')
        {
            cout << "YOU DIED";
            exit(0);
        }
        else
            cout << "请继续选择" << endl;
    }
    cout << "你成功存活了下来";
    return 0;
}

运行结果

也可以看一下生成的随机情况

int main()
{
    const unsigned tot_num = 1000000;
    default_random_engine e;
    bernoulli_distribution b;
    cout << boolalpha;
    unsigned flag = 0;
    for(int i=0;i<tot_num;++i)
    {
        if(b(e)) ++flag;
    }
    cout << static_cast<double>(flag) / static_cast<double> (tot_num);
    return 0;
}

 运行结果

很接近0.5了

在tot_num = 1000000000时

我们可以看见

 一些链接

default_random_engine - C++ Reference (cplusplus.com)icon-default.png?t=M276http://www.cplusplus.com/reference/random/default_random_engine/?kw=default_random_engineuniform_int_distribution - C++ Reference (cplusplus.com)icon-default.png?t=M276http://www.cplusplus.com/reference/random/uniform_int_distribution/?kw=uniform_int_distributionbernoulli_distribution - C++ Reference (cplusplus.com)icon-default.png?t=M276http://www.cplusplus.com/reference/random/bernoulli_distribution/?kw=bernoulli_distributionnormal_distribution - C++ Reference (cplusplus.com)icon-default.png?t=M276http://www.cplusplus.com/reference/random/normal_distribution/?kw=normal_distributionlround - C++ Reference (cplusplus.com)icon-default.png?t=M276http://www.cplusplus.com/reference/cmath/lround/?kw=lround

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++——随机数引擎和分布 的相关文章

  • 为 DocumentDb 设置自定义 json 转换器

    我正在使用类型化 DocumentQuery 从 Azure DocumentDb 集合中读取文档 from f in client CreateDocumentQuery
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • EF Core 返回 null 关系,直到直接访问

    我有一些如下所示的模型 public class Mutant public long Id get set Relations public long OriginalCodeId get set public virtual Origi
  • 如何使用C从http下载文件?

    最近几天我试图弄清楚如何从 URL 下载文件 这是我对套接字的第一个挑战 我用它来了解协议 所以我想在没有 cURL 库的情况下只用 C 语言来完成它 我搜索了很多 现在我可以打印页面的源代码 但我认为这与文件不同 我不必只将接收到的数据从
  • 与 MinGW 的静态和动态/共享链接

    我想从一个简单的链接用法开始来解释我的问题 假设有一个图书馆z它可以编译为共享库 libz dll D libs z shared libz dll 或静态库 libz a D libs z static libz a 让我想要链接它 然后
  • 带有 ASP.NET 按钮回发的 jQuery UI 对话框

    我的 ASP NET 页面上有一个运行良好的 jQuery UI 对话框 jQuery function jQuery dialog dialog draggable true resizable true show Transfer hi
  • 未找到 DEADLINE 调度策略

    我想在 C 中实现 DEADLINE 调度策略 我知道该功能已实现Linux 3 14 10我正在使用 Ubuntu 14 04Linux 3 17 0 031700 lowlatency 201410060605 SMP PREEMPT这
  • 非模板函数中的尾随返回类型[重复]

    这个问题在这里已经有答案了 我见过有人使用以下语法来实现函数 auto get next gt int 代替 int get next 我理解两者 并且我知道尾随返回类型语法对于使用 decltype 的模板代码很有用 就我个人而言 我会避
  • 如何从经过身份验证的 SecurityToken 中获取声明

    我将令牌作为字符串传递到 SOAP 服务中 并验证了该令牌是否有效 我现在有一个 SecurityToken 在调试模式下我可以看到所有声明 特别是我想传递到另一个方法的 userId 声明 我似乎不知道如何获得这些索赔 现在 我解码了令牌
  • 如何以编程方式删除受信任的根证书颁发机构中的证书?

    我需要能够从组织中的每台电脑中删除特定的证书 是的 我可以逐个座位 但我要到周四才能完成 而且我没有人力逐个座位 是否有使用 C 的编程方式来执行此操作 我认为你不需要编写任何 C 看看certmgr exe del http msdn m
  • 维护 VS Test Project 中单元测试方法之间的上下文

    我想按顺序运行以下单元测试 使用随机数字的名称 密码等创建新客户 检索刚刚创建的客户并断言其属性包含相同的随机数 对同一用户调用 ForgotPassword 函数 并使用相同的随机数作为用户名 清楚地看到 我需要生成一次随机数 并在 3
  • 注入包含接口的所有已注册实现的 Enumerable

    给出以下接口 public interface IMyProcessor void Process 我希望能够注册多个实现 并让我的 DI 容器将它们的可枚举注入到这样的类中 public class MyProcessorLibrary
  • 使用任一默认捕获模式时,这是通过复制捕获还是 (*this) 通过引用捕获?是一样的吗?

    当我看到以下工作时我有点困惑 struct A void g void f g 但后来我发现this https stackoverflow com a 16323119 5825294答案非常详细地解释了它是如何工作的 本质上 它归结为t
  • C# 可以为控制台应用程序部分类“程序”类吗?

    我想知道是否可以将为任何控制台应用程序创建的默认 程序 类更改为部分类 我想这样做是因为我想要更好的组织 而不是将所有方法都放在按区域分类的 1 个文件中 对我来说 将某些方法类别放在单独的文件中会更有意义 我对分部类的理解是 它是多个文件
  • 具有多个父项的 Qt 树模型

    我想构建一棵树 其中一个元素可以引用另一个元素 我想要构建的树是 像这样的东西 A B C D E F P this is a pointer to C D first child of C E second child of C I fo
  • Windows Phone 的 JSON 反序列化

    我正在尝试反序列化以下 JSON 但我真的不知道如何使用 JSON net 来完成这项工作 我正在使用 C 和 JSON Net 库 我的 JSON 如下 found 3 bounds 43 54919 172 62148 43 54487
  • 如何防止 Lotus Notes 用户转发或复制通过 System.Net.Mail 发送的邮件?

    我想使用 SMTP 客户端 uiing microsft net 以 C 作为编程语言发送电子邮件 但是对于通过SMTP客户端发送的电子邮件 我们是否可以添加 禁止转发 或 禁止复制 等安全功能 我不希望电子邮件的收件人转发或复制电子邮件的
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • C++ 中的析构函数

    我的 AB h 文件中有一个构造函数 class AB private int i public AB i 0 constructor AB i 0 destructor virtual void methodA unsigned int
  • 如何使用 Microsoft Graph API 更新 MailboxSettings

    我想从不同的日历更新邮箱设置 如何构建可以通过 Microsoft Graph 更新 MailboxSetting 的请求 这是我的代码示例 但有例外 代码示例 User obj GraphServiceClient Users roomC

随机推荐

  • 关于z域利用零极点快速判断滤波特性

    极点在右零点在左是低通 极点在左零点在右是高通 极点在零点中间是带通 零点在极点中间是带阻
  • 用Python语言编写账户类实现各种操作

    第一 先定义类后再创建账户 第二 写存款的实现方法 添加if进行判断存款的姓名和密码是否等于之前创建账户的信息 第三 写取款的 但要注意实现过程中满足之前存款大于取款 需要添加if来判断是否合理 第四 查询账户的各种信息 if判断查询账户姓
  • Unity 使用谷歌内购的密钥( license key )

    文章的内容主要是说明使用 Unity 接入谷歌内购IAP时 所需要的 license key 在哪里 如下图所示 看了下面的提示发现已经找不到这个 license key 了 打开 Google Play Console 在右侧找到创收设置
  • MFC通过com接口操作Excel

    整体思路 http wenku baidu com view d7383548767f5acfa1c7cd30 一些细节 对字体 边框 线条等操作引用Excel的枚举类型数据报错 提示没定义 的解决方案 打开头文件 把 import D P
  • MVC模式有哪些优缺点?

    优点 1 耦合性低 视图层和业务层分离 这样就允许更改视图层代码而不用重新编译模型和控制器代码 同样 一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可 因为模型与控制器和视图相分离 所以很容易改变应用程序的数据层和业务规则
  • Linux dstat监控工具简讲

    1 小声哔哔 记得在19年的年末 我第一次接触sar命令时将其奉为经典 至今看来仍不为过 可见我之前的博客 运维入门必备Linux sar命令 说回今天我们的工具dstat 与sar命令很相像 都很全面且强大 但是dstat更类似于看板 可
  • 成电信软程算I 雨课堂答案

    电子科技大学 信息与软件工程学院 程序设计与算法基础I 雨课堂答案 选择题因为限制 直接展示正确答案的文本选项 蓝色加粗为解析 第一章 程序设计引论 计算机系统由硬件和软件构成 它们共同工作来运行应用程序 程序员必须要关心底层硬件的细节 程
  • js实现二分查找算法

    js实现二分查找算法 二分查找 是一种搜索某个值的索引的算法 基本条件 有序的数组 思路 1 将数组折半 分成左右两个数组 2 判断要查找的数和中间位置数值的大小 来判断要查找的数实在哪一半 3 之后继续折半查找 直至找到这个数 方法 二分
  • nginx反向代理与负载均衡详解(四)

    用分片提升缓存效率 stream是双向通讯流 GRPC反向代理 前提http2 SLB服务器负载平衡 实时的视频或者音频时适合UDP协议
  • P1305 素数环

    include
  • springboot logback-spring.xml

    logback spring xml
  • Elasticsearch 结合dynamic-synonym实现同义词热加载

    Elasticsearch 本身支持的同义词配置如果需要修改同义词配置需重启es 灵活性不高 本章详细讲解通过结合dynamic synonym实现同义词热加载 通过sql定时获取数据库同义词配置 es版本 5 6 13 同义词插件 ela
  • 【Linux】linux进程间通信netlink socket(用户与内核通信) 一

    目录 1 基础概念 2 netlink socket 基本原理 3 用户空间常用socket APIs 3 1 socket 3 2 bind 3 3 sendmsg 3 4 send 3 5 recvmsg 3 6 close 4 net
  • chatGPT中国入口-ChatGPT评论文章-ChatGPT怎么用

    国内怎么玩chatGPT 如果您在国内使用ChatGPT 主要的问题可能是连接OpenAI服务器的速度和稳定性 由于OpenAI位于美国 可能受到中国的网络限制和防火墙的影响 造成访问速度比较慢或不稳定 为了解决这个问题 您可以采取以下方法
  • 为什么要分库分表(个人理解,希望能与大家共勉)

    前言 其实分库分表是牵扯到高并发的 因为分库分表无非来说就是为了支撑高并发 数据量大的问题 尤其进入稍微大一点的公司或者互联网公司 这些都是必须掌握 场景 假如一个新兴公司 刚开始时 注册用户就40W 每天活跃1W 每天单表数据量1000
  • Shark(鲨鱼记账系统)--附源码

    Shark 鲨鱼记账系统 附源码 程序员就要多撸代码 以便在脑海中形成深刻记忆 昨晚试着撸了一个小小的记账系统 内容很简单 主要负责简单的记账 不过没用到持久层 后续会做持久层的版本 先看个简单的把 package com shayu no
  • 十大Python可视化工具,太强了

    今天介绍Python当中十大可视化工具 每一个都独具特色 惊艳一方 Matplotlib Matplotlib 是 Python 的一个绘图库 可以绘制出高质量的折线图 散点图 柱状图 条形图等等 它也是许多其他可视化库的基础 import
  • 【复变函数与积分变换】【第一章 复数与复变函数】

    2021 1 3 文章目录 2021 1 3 第一章 复数与复变函数 1 1 复数 一 复数及其运算 定义 复数的基本概念 相等 四则运算 二 共轭复数 定义 性质 1 2 复数的几种表示 复平面 一 复数的模与辐角 主辐角 相互转换关系
  • Hydra(九头蛇)密码破解工具的详细使用教程

    简介 Hydra是 款开源的暴 密码pojie 具 持多种协议密码的破译 可以对多种服务的账号和密码进行爆破 包括 数据库 SSH FTP 等服务 在 Kali Linux 中自带 Hydra 有了这个工具就可以很方便的对密码进行破解 其简
  • C++——随机数引擎和分布

    随机数引擎是一个函数对象类 他们定义了一个调用运算符 不接受任何参数并且返回一个unsigned整数 我们可以适用其生成随机数 为什么称其为随机数引擎 因为我们通常不会直接适用引擎生成随机数 而是将其传入一个分布类对象中对齐进行分布生成 所