前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++11 的随机数的分析

C++11 的随机数的分析

原创
作者头像
zayyo
发布2023-11-30 00:09:15
3040
发布2023-11-30 00:09:15
举报
文章被收录于专栏:zayyo前端

C++11 是一个比较重要的版本,它引入了许多新的语言特性和标准库组件。其中,随机数生成的新特性极大地方便了开发人员在程序中生成随机数。

C++11 的随机数生成分为三个层次,包括随机数生成设备、随机数引擎和随机分布。下面分别对它们进行介绍。

产生随机数

C++11 的标准库提供了一个非确定性随机数生成设备,即 std::random_device。在 Linux 系统中,std::random_device 通过读取 /dev/urandom 设备来产生真随机数;而在 Windows 系统中,std::random_device 通过 rand_s 函数来产生伪随机数。使用 std::random_device 产生随机数时,可以通过调用其 operator() 方法返回一个 min()max() 之间的随机数。

代码语言:txt
复制
#include <iostream>
#include <random>
int main()
{
  std::random_device rd;
  for(int n=0; n<20000; ++n)
    std::cout << rd() << std::endl;
  return 0; 
}

随机数引擎

随机数引擎是一种伪随机数生成器,传入一个种子后,根据种子生成随机数。C++11 标准提供了三种常用的随机数引擎:std::linear_congruential_enginestd::mersenne_twister_enginestd::subtract_with_carry_engine。其中,std::linear_congruential_engine 是最常用的一种,速度也非常快;std::mersenne_twister_engine 则被称为最好的伪随机数生成器;std::subtract_with_carry_engine 目前还不太清楚。

使用随机数引擎时,可以通过传入一个整型参数作为种子,也可以使用默认值。如果想多次运行产生相同的随机数,可以使用一个确定的数作为种子;如果想每次运行生成不一样的随机数,则建议使用 std::random_device 产生一个随机数作为种子(Linux 下为真随机数,Windows 下为伪随机数)。

下面是一个示例代码,用于输出 10 个随机数:

代码语言:txt
复制
#include <iostream>
#include <random>
int main()
{
  std::random_device rd;
  std::mt19937 mt(rd());	// 梅森旋转算法
  for(int n = 0; n < 10; n++)
    std::cout << mt() << std::endl;
  return 0;
}

随机分布

STL 标准库还提供各种各样的随机分布,不过我们经常用的比较少,比如平均分布,正太分布…使用也很简单。随机分布是利用一定的算法处理 URBG 的输出,以使得输出结果按照定义的统计概率密度函数分布。

代码语言:txt
复制
//平均分布
#include <random>
#include <iostream>
int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, 6);
    for(int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';
    std::cout << '\n';
}

我们使用 std::random_device 生成种子,以防止使用相同的种子而导致每次程序运行生成相同的随机数序列。接着使用 std::mt19937 作为随机数引擎,生成均匀分布。最后,使用循环输出生成的随机数。

代码语言:txt
复制
//正太分布
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
 
    // values near the mean are the most likely
    // standard deviation affects the dispersion of generated values from the mean
    std::normal_distribution<> d(5,2);
 
    std::map<int, int> hist;
    for(int n=0; n<10000; ++n) {
        ++hist[std::round(d(gen))];
    }
    for(auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}

我们使用 std::normal_distribution 生成正态分布。其中,分布的期望为5,标准差为2。使用循环生成10000个随机数,并将每个数四舍五入到最接近的整数。接着使用 std::map 计算每个数出现的次数,并输出直方图。

总结和思考

我们对于随机数生成器,可以选择使用std::random_device作为种子,来保证生成的随机数更加随机。使用std::mt19937作为生成器,并结合不同的分布函数,可以生成不同类型的随机数。需要注意的是,在生成器初始化时,需要将种子传入生成器中。

对于分布函数,C++标准库提供了多种分布函数,如std::uniform_int_distribution用于生成均匀分布的整数,std::normal_distribution用于生成正态分布的随机数。分布函数需要结合生成器使用,从而生成具有特定分布特征的随机数。

我们在使用随机数生成器和分布函数时,需要考虑生成的随机数的范围和分布情况,以及生成的随机数是否满足要求。在进行模拟和实验时,随机数的质量直接影响着结果的准确性和可靠性。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 产生随机数
  • 随机数引擎
  • 随机分布
  • 总结和思考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档