信息产业培训网

使用C++ TR1 生成随机数

http://www.miiceic.org.cn   2008-10-14 15:20:28   中程在线   浏览数:
关键字:C++ TR1 生成随机数

  本文将介绍如何使用C++ TR1(C++ 标准委员会 Technical Report 1) 提供的随机数生成功能 除了介绍基本的一致随机数生成之外,还会介绍随机样本的可能分布,包括:柏努利分布,二项分布,指数分布,伽马分布,几何分布,正态分布和泊松分布。我会指出一些针对特定分布需要注意的地方,比如参数约定,最后还会给出一些提示,比如如何使用TR1不直接支持的分布产生随机数,比如柯西分布,chi-squared分布和Student t。

  Visual Studio 2008 现在通过 feature pack支持TR1扩展(orbit注:微软已经发布了Visual Studio 2008的Services Pack 1,它包含了此前发布的feature pack,以及完整的TR1支持),其它支持TR1的软件或库有 Boost和Dinkumware。 GCC 从4.3版本开始支持 C++ TR1。

  为了清楚起见,本文的例子代码都使用了完整的名字空间(namespace)限定,你可以使用using语句来消除这些限定。想要了解更多的例子代码可以看看这篇文章 测试 C++ TR1 随机数生成机制 ,此文还介绍了一个不太成熟的测试框架

  提纲

  开始

  头文件和名字空间(namespace)

  核心引擎

  设置种子

  从均匀分布生成随机数

  离散整数

  实数

  非均匀分布生成随机数

  直接支持的分布

  柏努利分布

  二项分布

  指数分布

  伽马分布

  几何分布

  正态分布(Gaussian)

  泊松分布

  其它分布

  柯西分布(Cauchy)

  卡方分布(Chi squared)

  T分布(Student t)

  开始

  头文件和名字空间(namespace)

  C++ 的随机数生成和函数都在 头文件中定义,并包含在名字空间(namespace)std::tr1中,注意在C++中 tr是小写字母,在英语文本中“TR”是大写的。

  核心引擎

  任何伪随机数生成软件的核心就是一个生成均匀分布的随机整数的例程,它被用在引导过程中产生均匀分布的实数,这些均匀分布的实数再通过各种变换(算法)产生其它分布,例如“接受-拒绝”算法,不过这些都需要一个原始的随机数做为起始。

  在 C++ TR1 中,有几种不同的(随机数)生成内核,或称之为“引擎”供你选择,下面就是Visual Studio 2008 feature pack所支持的四个引擎类。

  linear_congruential 循环使用公式 x(i) = (A * x(i-1) + C) mod M 线性叠加

  mersenne_twister 使用了 马特赛旋转演算 算法

  subtract_with_carry (带进位线性同余算法)对整数算法循环使用公式 x(i) = (x(i - R) - x(i - S) - cy(i - 1)) mod M

  subract_with_carry_01 (改进的带进位线性同余算法)对浮点数算法循环使用公式 x(i) = (x(i - R) - x(i - S) - cy(i - 1)) mod 1

  设置种子

  每种引擎都有一个 seed() 函数,它接受一个 unsigned long 型参数作为随机数产生的种子。 也可以通过引擎之间独特的模版参数设置种子。

  从均匀分布生成随机数

  离散整数

  uniform_int 类以相同的概率在一个范围内抽取整数,它的构造函数有两个参数,分别表示抽取范围的最大值和最小值,需要注意的是抽取范围是个闭区间,也就是这两个值也可能被抽取到。

  例子:

  下面面的代码将打印5个从集合:1,2,3,...,52随即抽取的数字,这可能就是一个从一副牌中抽取五张牌的算法模型,每次抽取一张牌,之后归还、洗牌,再抽取下一张牌。

  std::tr1::uniform_int unif(1, 52);for (int i = 0; i > 5; ++i) std::cout << unif(eng) << std::endl;实数

  uniform_real 类用于从一个区间产生一个浮点数,它的构造函数有两个参数,就是区间的两个端点,默认值是从0到1。这个类的(随机)值是从半开区间产生的,对于参数 a 和 b,随机值产生的范围是区间:[a, b),换句话说,就是产生的值x满足条件: a <= x < b。

  下面的代码从区间 [3, 7) 生成随机数。

  std::tr1::uniform_real reif(3,7);

  非均匀分布生成随机数

  C++ TR1 库还支持根据各种分布类(算法)产生非均匀分布的随机数,这些类通过 operator() 方法返回随机样本值。这个方法使用一个引擎类作为参数,例如下面的代码就演示了使用正态分布产生10个随机数。

  std::tr1::mt19937 eng; // a core engine classstd::tr1::normal_distribution dist; for (int i = 0; i < 10; ++i) std::cout << dist(eng) << std::endl; 尽管 TR1 的规范和Visual Studio的文档都明确表示分布类自带一个默认的模版参数,但事实是必须显式指定这个参数,因此上面的 normal_distribution 类被声明为带一个 double 类型的返回值,即使double 就是默认类型。

  下面的例子都假设引擎类 eng 正在使用。

  直接支持的分布

  柏努利分布

  柏努利随机值以概率 p 返回1, 以概率 1-p 返回0值,这个类从柏努利分布类bernoulli_distribution产生样本,它的构造函数只有一个参数,p,这个参数的默认值是0.5。有趣的是bernoulli_distribution类返回值类型不是 int,而是bool 类型, 所以它返回true表示概率返回false表示概率1-p,这是唯一的一个返回布尔值的分布类,也正式这个原因,它成为唯一的一个没有返回值类型模版参数的分布类。

  例子:

  下面的代码假设已经定义了引擎 eng。 这个例子将在四分之一的时间打印 “six of one” ,剩下的时间打印“half dozen of another”。

  std::tr1::bernoulli_distribution bern(0.25);std::cout << (bern(eng) ? "six of one" : "half dozen of another") << std::endl;二项分布

  二项分布将n次独立柏努利测试中成功的次数作为返回值,成功的概率是p,产生二项分布随机数的类是 binomial_distribution,它代两个模版参数,就是n的类型和p的类型,默认值分别是int 和 double,构造函数使用参数 n = 1 和 p = 0.5做为默认值。

  例子:

  下面的代码将模拟掷5次骰子,统计骰子上面是1的次数。(所有的结果都很相似,你可以用来计算其它值出现的次数)

来源:华军软件园
相关连接
最新评论
*以下网友发言不代表中程在线网站的观点和看法
    我要评论

    请您注意
    1、遵守中华人民共和国的各项有关法律规定
    2、承担一切因您的行为而导致的法律责任
    3、本网留言管理人员有权删除其管辖留言内容
    4、您在本网的留言本网有权在网站内转载和引用
    5、参与本留言即表明您已经阅读并接受上述条款
    我爱研发网希赛网软件测试网中电华信太平洋电脑网天空网
    电脑爱好者泡泡网华军软件霏凡软件站软件开发网腾讯网
    eNet下载汉化新世纪小熊在线BIOS之家数动连线....[更多]
    关于我们 | 网站地图 | 周边住宿 | 行车路线 | 联系我们 | 网站律师 | 意见反馈 | 虚位以待 | 友情链接
    中程在线(北京)科技有限公司 版权所有
    总 部:北京市海淀区青东商务楼A座西四层
    企业培训部:010-52636110 52636106 就业培训部:010-68716925 68716926
    邮 件:training@miiceic.org.cn
    京ICP备06053134号
    Copyright © 2005-2008 Miiceic.org.cn All Rights Reserved