C++随机数

伪随机数

int rand(void)函数通常用来当做随机函数来使用,殊不知这其实是一个伪随机函数。按照某种顺序生成的随机函数,这是什么意思呢?我们来测试一下,

第一次:

     cout << "first:" << endl;
    cout << rand() << endl;
    cout << rand() << endl;
    cout << rand() << endl;

第一次结果
第二次
第二次结果
发现,只要程序重复运行每次生成的随机数都是一样的!!这就是伪随机数的概念。如何改进呢?

种子

我们力求每次都要随机成功,引入一个随机数种子的概念,种子和随机数的产生是有因果关系的,同一个种子,只会产生同一种随机数,随机数种子是由一个种子函数来指定的,它就是void srand(unsigned int seed),当没有设置的时候,系统默认是1,我们要保证每次进入系统种子都会改变,通常的习惯是用时间来定为种子,因为时间一直在流逝,time(NULL)返回一个1970-1-1 00:00:00到当前时间的秒数。可以做为种子。
srand(time(NULL))
就像这样

int _tmain(int argc,TCHAR* argv[])
{
    srand((unsigned)time(NULL));
    cout << rand() << endl;
    cout << rand() << endl;
    cout << rand() << endl;
    cin.get();
    return 0;
} 
  • 先指定再使用。严格的说这个还是一个伪随机函数 ,但也基本达到了完全随机的效果。

获得两个区间之间的随机值,普遍想到的方法是:
要取得[a,b)的随机整数,使用(rand() % (b-a))+ a;
要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a;
要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1;

这个办法很好理解,但是我喜欢先得到0-1之间的随机值,再乘以b-a,最后再加上a。

double dVal = ((double)rand()/RAND_MAX)
return  iMin + dVal *  (iMax - iMin)  

确定区间的方法都是一样的,理解哪个用哪个!


思考

我们虽然写出了相对随机的随机数函数,但是细心的人会发现一个问题,就是随机数区间的概率问题,假如我们需要求1到3之间的随机数,我们期望是等概率的,但是事实却不是。

我们知道,rand()函数获得的区间是[0,RAND_MAX),假若用求余数的方法,RAND_MAX的值是0x7fff,可得(0x7fff-1)%3=0,看上去好像每个数出现的次数一致,别忘了我们还包含一个0,也就是说0出现的次数多,不是等概率的。

  • 具体怎么办留给大家思考,欢迎在评论区探讨
posted @ 2016-12-10 18:55  机智的程序员小熊  阅读(130)  评论(0编辑  收藏  举报