admin管理员组

文章数量:1794759

C++11中随机数生成器(random)

C++11中随机数生成器(random)

目录
  • 1 随机数生成器的分类
  • 2 随机数据引擎
    • 2.1 线性同余法引擎
    • 2.2 梅森旋转法引擎
    • 2.3 滞后Fibonacci引擎
    • 2.4 非确定随机生成器
    • 2.5 默认随机数引擎
  • 3 随机数适配器
    • 3.1 std::discard_block_engine
    • 3.2 std::independent_bits_engine
    • 3.3 std::shuffle_order_engine
  • 4 随机数分布类
    • 4.1 均匀分布:
    • 4.2 伯努利类型分布:(仅有yes/no两种结果,概率一个p,一个1-p)
    • 4.3 泊松分布:
    • 4.4 正态分布相关:
    • 4.5 分段分布相关:
  • 5 小工具
    • 5.1 generate_canonical
    • 5.2 seed_seq
  • 6 示例
  • 7 参考

1 随机数生成器的分类
  • Uniform random bit generators (URBGs,随机数生成器/随机数引擎): 生成某一类型最小到最大范围内的均匀分布随机数据
  • Random number distributions(随机数分布类):将URBGs转成某种分布,如,均匀分布,正态分布等
  • 一般随机数生成器和随机数生成类配合使用,去生成随机数据。

    2 随机数据引擎 2.1 线性同余法引擎

    类的声明,由于实现了operator(),所以他是一个仿函数类。

    template< class UIntType, // The result type generated by the generator. The effect is undefined if this is not one of unsigned short, unsigned int, unsigned long, or unsigned long long UIntType a, // the multiplier term UIntType c, // the increment term UIntType m // the modulus term > class linear_congruential_engine;

    random库贴心的帮我们typedef了两个类型,防止我们不知道怎么设置参数 😃

    // Discovered in 1969 by Lewis, Goodman and Miller, adopted as "Minimal standard" in 1988 by Park and Miller using minstd_rand0 = std::linear_congruential_engine<std::uint_fast32_t, 16807, 0, 2147483647> // Newer "Minimum standard", recommended by Park, Miller, and Stockmeyer in 1993 using minstd_rand = std::linear_congruential_engine<std::uint_fast32_t, 48271, 0, 2147483647> 2.2 梅森旋转法引擎

    类的声明,同样也是仿函数类

    template< class UIntType, std::size_t w, std::size_t n, std::size_t m, std::size_t r, UIntType a, std::size_t u, UIntType d, std::size_t s, UIntType b, std::size_t t, UIntType c, std::size_t l, UIntType f > class mersenne_twister_engine;

    typedef的类型

    // 32-bit Mersenne Twister by Matsumoto and Nishimura, 1998 using mt19937 = std::mersenne_twister_engine<std::uint_fast32_t, 32, 624, 397, 31, 0x9908b0df, 11, 0xffffffff, 7, 0x9d2c5680, 15, 0xefc60000, 18, 1812433253>; // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 using mt19937_64 = std::mersenne_twister_engine<std::uint_fast64_t, 64, 312, 156, 31, 0xb5026f5aa96619e9, 29, 0x5555555555555555, 17, 0x71d67fffeda60000, 37, 0xfff7eee000000000, 43, 6364136223846793005>; 2.3 滞后Fibonacci引擎

    类的声明,也是反函数类

    template< class UIntType, std::size_t w, std::size_t s, std::size_t r > class subtract_with_carry_engine;

    typedef的类型

    using ranlux24_base = std::subtract_with_carry_engine<std::uint_fast32_t, 24, 10, 24> using ranlux48_base = std::subtract_with_carry_engine<std::uint_fast64_t, 48, 5, 12> 2.4 非确定随机生成器

    类的声明

    class random_device;

    它并不是由某一个数学算法得到的随机序列,而是通过读取文件,读什么文件看具体的实现(Linux可以通过读取/dev/random文件来获取)。文件的内容是随机的,因为文件内容是计算机系统的熵(熵指的是一个系统的混乱程度)。也是当前系统的环境噪声,系统噪音可以通过很多参数来评估,如内存的使用,文件的使用量,不同类型的进程数量等等。Linux的熵来自键盘计时、鼠标移动等。 在没有非确定源(如硬件设备)时他会产生伪随机数,此时每一个random_device的对象会产生相同的随机数序列

    例子:

    #include <iostream> #include <random> void demo(std::random_device&& rd) { for(int n = 0; n != 10; ++n) { std::cout << rd() << ' '; } std::cout << '\\n'; } int main() { // Note: How the supplied token is handled is implementation-defined! // Default token for random_device is usually /dev/urandom on Linux demo(std::random_device{}); // Request /dev/random, blocks when entropy is empty // Works on libstdc++, ignored in msvc++, might throw on libc++ (as of Nov 2022) demo(std::random_device{"/dev/random"}); // Request non-blocking /dev/urandom, ensures that RDRAND is not used // Works on libstdc++ and libc++, ignored in msvc++ (as of Nov 2022) demo(std::random_device{"/dev/urandom"}); // Request "hw", will use hardware-based random generation like rdrand // Works on libstdc++, ignored in msvc++, throws on libc++ (as of Nov 2022) demo(std::random_device{"hw"}); } 2.5 默认随机数引擎 std::default_random_engine; // 由编译器定义 3 随机数适配器

    随机数适配器的作用就是对上述引擎产生的随机序列进行修饰和适配。

    3.1 std::discard_block_engine

    它丢弃由基本引擎产生的一定数量的数据。从每一块大小P由基本引擎生成的适配器只保留R数字,丢弃剩下的。

    类声明

    template< class Engine, std::size_t P, std::size_t R > class discard_block_engine;

    typedef的类型

    // 24-bit RANLUX generator by Martin Lüscher and Fred James, 1994 using ranlux24 = std::discard_block_engine<std::ranlux24_base, 223, 23>; // 48-bit RANLUX generator by Martin Lüscher and Fred James, 1994 using ranlux48 = td::discard_block_engine<std::ranlux48_base, 389, 11>; 3.2 std::independent_bits_engine

    independent_bits_engine是一个随机数引擎适配器,它产生与包装引擎不同位数的随机数。

    类的声明

    template< class Engine, std::size_t W, class UIntType > class independent_bits_engine; 3.3 std::shuffle_order_engine

    他会对随机数引擎产生的序列随机重排,并将其保存在大小为k的表中,当有请求是从中选择一个返回,之后使用随机数引擎产生一个随机数填补这个位置。

    类的声明

    template< class Engine, std::size_t K > class shuffle_order_engine;

    typedef的类型

    using knuth_b = std::shuffle_order_engine<std::minstd_rand0, 256>; 4 随机数分布类

    随机数分布类可以将随机数引擎产生的随机数转成特定分布输出,如整型均匀分布(std::uniform_int_distribution):

    类的声明

    template< class IntType = int > class uniform_int_distribution;

    例子

    #include <iostream> #include <random> int main() { std::random_device rd; // Will be used to obtain a seed for the random number engine std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> distrib(1, 6); // Use distrib to transform the random unsigned int // generated by gen into an int in [1, 6] for (int n = 0; n != 10; ++n) std::cout << distrib(gen) << ' '; std::cout << '\\n'; } 4.1 均匀分布:
    • uniform_int_distribution 整数均匀分布
    • uniform_real_distribution 浮点数均匀分布
    4.2 伯努利类型分布:(仅有yes/no两种结果,概率一个p,一个1-p)
    • bernoulli_distribution 伯努利分布
    • binomial_distribution 二项分布
    • geometry_distribution 几何分布
    • negative_biomial_distribution 负二项分布
    4.3 泊松分布:
    • poisson_distribution 泊松分布
    • exponential_distribution指数分布
    • gamma_distribution 伽马分布
    • weibull_distribution 威布尔分布
    • extreme_value_distribution 极值分布
    4.4 正态分布相关:
    • normal_distribution 正态分布
    • lognormal_distribution 对数正态分布
    • chi_squared_distribution 卡方分布
    • cauchy_distribution 柯西分布
    • fisher_f_distribution 费歇尔F分布
    • student_t_distribution t分布
    4.5 分段分布相关:
    • discrete_distribution离散分布
    • piecewise_constant_distribution分段常数分布
    • piecewise_linear_distribution分段线性分布
    5 小工具 5.1 generate_canonical

    std::generate_canonical 可以产生[0,1)范围内随机浮点数

    类的声明

    template< class RealType, std::size_t Bits, class Generator > RealType generate_canonical( Generator& g );

    例子

    #include <random> #include <iostream> int main() { std::random_device rd; std::mt19937 gen(rd()); for(int n=0; n<10; ++n) { std::cout << std::generate_canonical<double, 10>(gen) << ' '; } } 5.2 seed_seq

    他可以产生无符号整型范围内的值序列 类的声明

    class seed_seq;

    例子

    #include <random> #include <cstdint> #include <iostream> int main() { std::seed_seq seq{1,2,3,4,5}; std::vector<std::uint32_t> seeds(10); seq.generate(seeds.begin(), seeds.end()); for (std::uint32_t n : seeds) { std::cout << n << '\\n'; } }

    输出

    4204997637 4246533866 1856049002 1129615051 690460811 1075771511 46783058 3904109078 1534123438 1495905678 6 示例 #include <cmath> #include <iomanip> #include <iostream> #include <map> #include <random> #include <string> int main() { // Seed with a real random value, if available std::random_device r; // Choose a random mean between 1 and 6 std::default_random_engine e1(r()); std::uniform_int_distribution<int> uniform_dist(1, 6); int mean = uniform_dist(e1); std::cout << "Randomly-chosen mean: " << mean << '\\n'; // Generate a normal distribution around that mean std::seed_seq seed2{r(), r(), r(), r(), r(), r(), r(), r()}; std::mt19937 e2(seed2); std::normal_distribution<> normal_dist(mean, 2); std::map<int, int> hist; for (int n = 0; n != 10000; ++n) ++hist[std::round(normal_dist(e2))]; std::cout << "Normal distribution around " << mean << ":\\n" << std::fixed << std::setprecision(1); for (auto [x, y] : hist) std::cout << std::setw(2) << x << ' ' << std::string(y / 200, '*') << '\\n'; } 7 参考
  • Pseudo-random number generation
  • c++ 11 random库的简单用法
  • C++11 随机数学习
  • 本文标签: 随机数生成器random