c++进阶STL-随机数

野性酷女 2021-12-20 16:49 361阅读 0赞

文章目录

    • 介绍
    • 知识点
      • 库中的Distribution 和 Engine
      • 生成随机序列
      • 其他类型分布
        • 浮点数分布
        • Normal Distribution
        • Bernoulli distribution

介绍

在新的标准之前,C和C++产生随机数都依赖与简单的C库函数rand(),这个函数产生一个伪随机数均匀分布在[0-system dependent maximum value(at least 32767)]。

但是rand()函数存在问题:有的程序需要不同的随机数范围,有的程序需要浮点随机数,有的程序可能需要的不是均匀分布的随机数。所以在程序员处理、转换这些问题的时候往往可能引入不随机的特性

为了解决这个为题,新的c++库引入随机数库,定义在 头文件中,主要两个类:














Engine Distribution
生成无符号整型的随机序列 利用Engine,根据特定的分布,返回随机数

random-number generator:指的是distribution 的对象关联一个Engine

知识点

库中的Distribution 和 Engine

详见: c++ prime p883-p885


















































































































distribution 说明
均匀分布 **
uniform_int_distribution<types> u(m,n) 产生[m,n]均匀分布的整数
uniform_real_distribution<types> u(m,n) 产生[m,n]默认[0-1]均匀分布的实数
伯努利分布 **
bernoulli_distribution b( p )
binomial_distribution<types>b(t, p)
geometric_distribution<types> g( p )
negative_binomial_distribution<types> nb(k, p)
泊松分布 *
poisson_distribution<types> p(x)
exponential_distribution<types> e (lam)
gamma_distribution <types> g(a, b)
weibull_distribution<types> w (a, b)
正态分布 *
normal_distribution<types> n (m, s)
lognomal_distribution<types> ln (m, s)
chi_squared_distribution<types> c ( x )
cauchy_distribution<types> c (a, b)
fisher_fdistribution<types> f (m, n)
student_tdistribution<types> s( n)
抽样分布 *
discrete_distribution<types> d( i, j )
discrete__distribution<types> d { il }
piecewise_constant_distribution<types> pc(b, e, w)
piecewise_linear_distribution<types> pl(b, e, w)





































Engine 说明
default_random_engine
shuffle_order_engine
linear_congruential_engine
mersenne_twister_engine
subtract_with_carry_engine
discard_block_engine
independent_bits_engine

生成随机序列

  • 我们需要注意的是:一个给定的random-number generator每次生成的序列都是一样的(这种情况有时候便于调试),如下代码:

    vector bad_randVec()
    {

    1. default_random_engine e;
    2. uniform_int_distribution<unsigned int> u(0, 9);
    3. vector<unsigned int> ret;
    4. for(int i=0; i<10; i++)
    5. ret.push_back(u(e));
    6. return ret;

    }

如果想每个调用这个函数每次生成的序列不一样,有两种方案:

  1. (利用static):

    vector bad_randVec()
    {

    1. static default_random_engine e;
    2. static uniform_int_distribution<unsigned int> u(0, 9);
    3. vector<unsigned int> ret;
    4. for(int i=0; i<10; i++)
    5. ret.push_back(u(e));
    6. return ret;

    }

  2. 利用seed

    • 手动提供种子

    defalut_random_engine e(32767); //第一种:初始化的时候
    e.seed(32767) // 第二种: 初始化之后,调用成员函数

  • 利用time()函数,头文件

    defalut_random_engine e(time(0));

  • 利用random_device,random_device提供()操作符,用来返回一个min()到max()之间的一个数字.可以理解真随机数

    std::random_device rd;
    defalut_random_engine e(rd(0));

其他类型分布

浮点数分布

以前通常是使用 rand()/RADN_MAX来产生[0 1]的实数均匀分布。但这是不准确的,因为int型相比于浮点数通常是精确度低,所以有的浮点数永远不会生成。

  1. default_random_engine e;
  2. uniform_real_distribution<double> u(0,1);
  3. for(size_t i=0; i<10; i++)
  4. cout << u(e) << " ";

注意:如果想使用默认的数据类型的分布(通常浮点数:double, 整数:int), 我们传递模板参数为空,如:uniform_real_distribution<> u(0,1)

Normal Distribution

  1. default_random_engine e;
  2. normal_distribution<> n(4, 1.5);
  3. vector<unsigned> vals(9); //记录0-9的每个数字的个数
  4. for(size_t i=0; i<200; i++)
  5. {
  6. unsigned v = lround(n(e));
  7. if(v< vals.size())
  8. ++vals[v];
  9. }
  10. for(size_t j=0; j!= vals.size(); ++j)
  11. cout << j << ": " << string(vals[j], '*') << endl;

在这里插入图片描述

Bernoulli distribution

这不是一个模板类,是一个普通类,返回总是bool value
举例:假如你和电脑玩游戏,总有一个人先开始,who is first,我们可以通过 uniform_int_distribution (0, 1); 或者可以通过Bernoulli distribution来make a choice。

  1. string resp;
  2. default_random_engine e;
  3. bernoulli_distribution b; // 默认 返回 true : false = 0.5 : 0.5
  4. //bernoulli_distribution b(0.55); // 返回 true:false = 0.55:0.45
  5. do
  6. {
  7. bool first = b(e);
  8. cout << (first ? "computer first" : "you first") << endl;
  9. cout << (play_game(first) ? "sorry, you lost" : "congratulations, you won" ) << endl;
  10. cout << "pay again? enter yes or no" << endl;
  11. }while(cin >> resp && resp[0] == 'y')

值得注意的是,我们 declare engine outside of loops,所以每次产生结果不一样,如果在loop内声明的话,每次的结果都是一样的

发表评论

表情:
评论列表 (有 0 条评论,361人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++STL-函数对象

    函数对象的概念  重载  ()操作符  的类,它的对象叫做函数对象,即它是 类似于函数的 对象(它可以向函数一样调用),也叫作仿函数。 注意:函数对象(

    相关 C++STL-异常处理

    异常抛出是跨函数的 返回值:只是返回给调用的这一层函数 异常:最里面的函数func1如果抛出异常给 调用的func2 , 如果func2没有处理, 再抛出给调

    相关 C++STL-模板

    模板的机制 模板并不是能处理任何类型的数据,只是它根据传入参数的类型的不同生成了不同的 函数/类 体(我们在不使用函数模板的正常操作,只不过编译器帮我们做了)。在此编译过