注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

ocean's blog

平常心——可以寂寞,但不允许空虚

 
 
 

日志

 
 

随机数  

2009-06-09 22:08:34|  分类: C++(转) |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

多样化是生活的一大乐趣,而计算机却似乎完全是可预见的,因此显得较死板,随机数为计算机程序注入了不可预见的东西,因此可以让计算机更好地模拟外部事件。比如游戏,图形显示,计算机仿真,随机数增加了许多的乐趣,而且当计算机程序重复运行时,不会表现出跟它模仿的自然系统有什么不同之处。


我们打算设计一个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;

/*************************************************************************/
//类声明:

class Random ...{
public:
   Random(bool pseudo = true);         // 构造函数
   double random_real();                // 产生0~1之间的实数
   int random_integer(int low, int high);  // 产生low ~~ high 之间的整形随机数
   int poisson(double mean);            // 泊松分布
 private:
   int reseed();                        //  Re-randomize the seed.
   int seed,
       multiplier, add_on;               //  constants for use in arithmetic operations
};

/*
核心函数是下面这个更新随机种子的reseed函数,给其他函数调用来产生随机化行为。
*/


int Random::reseed()
/**//*
Post: The seed is replaced by a pseudorandom successor.
*/
...{
   seed = seed * multiplier + add_on;
   return seed;
}

/* 常量multiplier和add_on保存在类得数据成员中,它们不应该随便选择,应该谨慎选择以保证结果的随机性,使其能多次变换。例如下面构造函数的值在16位机中表现得很好
*/

Random::Random(bool pseudo)
/**//*
Post: The values of seed, add_on, and multiplier are
      initialized.  The seed is initialized randomly only if pseudo == false.
*/
...{
   if (pseudo) seed = 1;
   else seed = time(NULL) % INT_MAX;
   multiplier = 2743;
   add_on = 5923;
}

/*
为了产生不可测的种子,我们用到了函数time(),它是包含在time.h头文件中,它计算从1970年开始流逝过的时间,单位是秒。INT_MAX是int型变量的最大值
*/

double Random::random_real()
/**//*
Post: A random real number between 0 and 1 is returned.
*/
...{
   double max = INT_MAX + 1.0;
   double temp = reseed();
   if (temp < 0) temp = temp + max;
   return temp / max;
}

/*
下面这个函数是产生的随机数形式是整形数。实际上,我们说随机整数是不准确的,因为整形数是无限的,而计算机表示的数是有限的。因此一个真正的随机数是计算机表示的数中的一个的概率是0。 而我们只考虑在low ~ high 之间的整数。
*/

int Random::random_integer(int low, int high)
/**//*
Post: A random integer between low and high (inclusive) is returned.
*/
...{
   if (low > high) return random_integer(high, low);
   else return ((int) ((high - low + 1) * random_real())) + low;
}

/*
泊松分布(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的泊松分布.  理论推导与证明省略。
*/

int Random::poisson(double mean)
/**//*
Post: A random integer, reflecting a Poisson distribution
      with parameter mean, is returned.
*/
...{
   double limit = exp(-mean);
   double product = random_real();
   int count = 0;
   while (product > limit) ...{
      count++;
      product *= random_real();
   }
   return count;
}

/*************************************************************************/


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 之间的一个随机数.


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/touzani/archive/2007/05/22/1620072.aspx

  评论这张
 
阅读(94)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018