多样化是生活的一大乐趣,而计算机却似乎完全是可预见的,因此显得较死板,随机数为计算机程序注入了不可预见的东西,因此可以让计算机更好地模拟外部事件。比如游戏,图形显示,计算机仿真,随机数增加了许多的乐趣,而且当计算机程序重复运行时,不会表现出跟它模仿的自然系统有什么不同之处。
我们打算设计一个class Random, 它的成员函数生成和返回各种各样的随机数。
将要生成随机数的思想是,从一个数出发,对它进行一系列的算术运算,产生一个与开始那个数没有明显的关系的一个数。因此通过这种方法产生的数实际上一点也不随机,因为每一个数都依赖于它之前的一个数,而且这种依赖是固定的。我们应该更确切地叫它伪随机数(pseudorandom)。那个开始的数叫做随机种子(seed).
如果程序每次都从同一个种子开始运行,那么得到的整个伪随机数序列将会是完全一样的。因此我们可以产生任意已经得到过的实验结果。然而,假如客户希望随机数不仅是不可预测(unpredicable),而且还要不可重复生成的(unproducible)。因此我们应该提供一个根据现在的时间(精确到秒)来产生随机种子。因为程序每次运行的时刻很可能是不同的,这种初始化的方式会使客户程序每一次运行产生不同的行为。
我们打算为class Random提供一个构造函数,用一个参数bool pseudo来提供两种初始化随机种子的方式。当pseudo==true, 将用预定义的种子来产生随机数,反之,当pseud==false, 我们将产生unproducible的随机数。这种情况下,客户也无需特别地去初始化随机种子,程序会自动根据当前时间来初始化之。
源代码
//使用类应包括下列头文件
#include<iostream> // cout, cin, NULL
#include<climits> // <limits.h> define INT_MAX
#include<ctime> // or <time.h>
#include<cmath> // or <math.h>
#include<iomanip> // setprecision(std::streamsize)
using namespact std;
/*************************************************************************/
//类声明:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
/*
核心函数是下面这个更新随机种子的reseed函数,给其他函数调用来产生随机化行为。
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
/* 常量multiplier和add_on保存在类得数据成员中,它们不应该随便选择,应该谨慎选择以保证结果的随机性,使其能多次变换。例如下面构造函数的值在16位机中表现得很好
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
/*
为了产生不可测的种子,我们用到了函数time(),它是包含在time.h头文件中,它计算从1970年开始流逝过的时间,单位是秒。INT_MAX是int型变量的最大值
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
/*
下面这个函数是产生的随机数形式是整形数。实际上,我们说随机整数是不准确的,因为整形数是无限的,而计算机表示的数是有限的。因此一个真正的随机数是计算机表示的数中的一个的概率是0。 而我们只考虑在low ~ high 之间的整数。
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
/*
泊松分布(Poisson distribution)
我们从称一个正实数为随机数的期望值(expected value)开始,如果一个非负整数序列满足期望值为v的泊松分布,那么足够长的子序列的平均值【mean(average) value】将趋近于v
例如期望值为1.5,我们可能读入一个序列: 1, 0, 2, 2, 1, 1, 3, 0, 1, 2, 0, 0, 2, 1, 3, 4, 2, 3, 1, 1, ....如果你计算子序列的平均值的话,你会发现有时小于1.5,有时大于,但慢慢地,它总的趋势会是1.5。
下面这个函数产生平均值为mean的泊松分布. 理论推导与证明省略。
*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
/*************************************************************************/
C/C++头文件<cstdlib>(注:新版编译器支持) 或<stdlib.h>(注:旧式的头文件格式)提供了生成随机数的函数。 这些函数可以替代本文中的函数。但是系统生成的随机数有时不是很理想,因此值得研究怎么构造更好的随机数。
比如
srand((unsigned)time( NULL ) ); //Seed the random-number generator with current time so that the //numbers will be different every time we run.
int i=rand()%(r-p)+p; // rand() 返回0-RAND_MAX (32767)的伪随机数
这样得到i就会是p ~ r 之间的一个随机数.