C++初学者指南-5.标准库(第二部分)–随机数生成

基本概念

例子

统一随机数

#include <random>
// fixed seed(固定种子)
auto const seed = 123;
// Mersenne Twister random engine(梅森旋转随机引擎):
std::mt19937 urbg {seed};  
// generate random ints ∈ [1,6](生成1-6之间的随机整数)
std::uniform_int_distribution<int> distr1 {1, 6};
auto const value1 = distr1(urbg);
auto const value2 = distr1(urbg);
// generate random floats ∈ [-1.2,6.25)(生成-1.2到6.25之间的随机浮点数)
std::uniform_real_distribution<float> distr2 {-1.2f, 6.25f};
auto const value3 = distr2(urbg);

运行示例代码

布尔值(“抛硬币”)

#include <random>
auto const seed = 123;
auto urbg = std::mt19937 {seed};  
// unfair coin (40% 'true'):
double const p = 0.4;  
auto flip = std::bernoulli_distribution{p};
if (flip(urbg))  // 40% chance
  cout << "heads\n";
else  // 60% chance
  cout << "tails\n";

C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP
运行示例代码

正态分布

#include <random>
auto const seed = 123;
auto urbg = std::mt19937 {seed};  
double const mu = 4.0; 
double const sigma = 0.7; 
auto norm = std::normal_distribution<double>{mu,sigma};
auto value = norm(urbg);

C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP
运行示例程序

具有独立概率的整数

#include <random>
auto const seed = std::random_device{}();
auto urbg = std::mt19937{seed};  
std::vector<double> ws {1.0, 1.5, 0.5, 2.0};
std::discrete_distribution<int> distr {begin(ws), end(ws)};
std::vector<int> histo (ws.size(), 0);
int const N = 100000;
for (int k = 0; k < N; ++k) {
  auto const i = distr(urbg);
  ++histo[i];
}
std::cout << "Histogram:\n";
for (auto x : histo) {
  auto const size = int(30 * x/double(N));
  cout << std::string(size,'-') << "o\n";
}

C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP
运行示例程序

怎么做

种子引擎

#include <random>
#include <chrono>  // clocks
auto e = std::mt19937{};
// seed engine with a constant
e.seed(123);
// … or with system clock ticks
auto const ticks = std::chrono::system_clock::now().time_since_epoch().count();
e.seed(ticks);
// … or with hardware entropy
auto const hes = std::random_device{}();
e.seed(hes);
// … or with a seed sequence
std::seed_seq s {1,5,3,7,0,9};
e.seed(s);
auto distr = std::uniform_real_distribution{-11.0, 15.3};
cout << distr(e) << '\n';

运行示例代码

使用自定义生成器

Lambda生成器

  • 在 lambda 捕获中初始化引擎和分发
  • 重要:lambda 必须标记为 mutable 因为内部状态 引擎和分配需要随着每次调用而改变
#include <random>
auto const seed = std::random_device{}();
auto coin_flip = [
  // init-capture engine + distribution:
  urbg = std::mt19937{seed},
  distr = std::bernoulli_distribution{0.5}
]() mutable -> bool { return distr(urbg); };
// use generator:
cout << coin_flip() << '\n';
auto roll = [
  urbg = std::mt19937{seed},
  distr = std::uniform_int_distribution<int>{1,6}
]() mutable -> int { return distr(urbg); };
cout << roll() << '\n';

运行示例程序

自定义生成器类
如果需要对参数进行更多控制

#include <random>
class DiceRoll {
  using engine_type = std::mt19937;
  // engine + distribution as members:
  engine_type urbg_;
  std::uniform_int_distribution<int> distr_;
public:
  using seed_type = engine_type::result_type;
  // constructor:
  explicit 
  DiceRoll (int sides, seed_type seed = 0) noexcept: 
    urbg_{seed}, distr_{1,sides} {}
  // allows to re-seed
  void seed (seed_type s) noexcept { urbg_.seed(s); }
  // call operator:
  int operator () () noexcept { return distr_(urbg_); }
};

int main () {
  auto const seed = std::random_device{}();
  DiceRoll roll_d20 {20, seed};
  std::cout << roll_d20() << '\n';
}

运行示例程序

shuffle算法

C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP
cppreference

#include <algorithm>
#include <random>
// 32 bit mersenne twister engine
auto const seed = std::random_device{}();
auto reng = std::mt19937{seed};
std::vector<int> v {0,1,2,3,4,5,6,7,8};
shuffle(begin(v)+2, begin(v)+7, reng);  
for (int x : v) { cout << x <<' '; }  // 0 1 … 7 8

运行示例代码
C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP

分布类型概述

通用接口

均匀分布

采样分布

伯努利分布

正态分布

泊松分布

概览表

C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP
C++初学者指南-5.标准库(第二部分)–随机数生成-LMLPHP

引擎类型概述

通用引擎接口

相关内容

Random Generator: Combining Engine + Distribution
Random Number Sequences: Control Reproducibility
cppreference: Pseudo-Random Number Generation
cppreference: std::generate_canonical
What C++ Programmers Need to Know about Header  (Walter E. Brown, 2016)

附上原文链接
如果文章对您有用,请随手点个赞,谢谢!^_^

10-04 22:23