Chinaunix首页 | 论坛 | 博客
  • 博客访问: 701721
  • 博文数量: 102
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 1748
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-23 15:42
个人简介

寻找严肃、沉默和专注的力量。

文章分类

全部博文(102)

文章存档

2015年(26)

2014年(8)

2013年(68)

分类: C/C++

2013-05-31 17:08:22

本文转载自:http://www.cnblogs.com/U2USoft/archive/2007/03/02/662115.aspx


标准库(被包含于中)提供两个帮助生成伪随机数的函数:


函数一:int rand(void);
从srand (seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。


函数二:void srand(unsigned seed);
参数seed是rand()的种子,用来初始化rand()的起始值。


可以认为rand()在每次被调用的时候,它会查看:
1) 如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用
srand(seed)一次来初始化它的起始值。
2) 如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。


根据上面的第一点我们可以得出:
1) 如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
2) 否则,如果给seed指定的是一个定值,那么每次程序运行时rand()产生的值都会一样,虽然这个值会是[seed, RAND_MAX(0x7fff))之间的一个随机取得的值。
3) 如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。


举几个例子,假设我们要取得0~6之间的随机整数(不含6本身):


例一,不指定seed:
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2


例二,指定seed为定值1:
srand(1);
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2
跟例子一的结果完全一样。


例三,指定seed为定值6:
srand(6);
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<
}
每次运行都将输出:4 1 5 1 4 3 4 4 2 2
随机值也是在[0,6)之间,随得的值跟srand(1)不同,但是每次运行的结果都相同。


例四,指定seed为当前系统流逝了的时间(单位为秒):time_t time(0):
#include
//…
srand((unsigned)time(0));
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<
}
第一次运行时输出:0 1 5 4 5 0 2 3 4 2
第二次:3 2 3 0 3 5 5 2 2 3
总之,每次运行结果将不一样,因为每次启动程序的时刻都不同(间隔须大于1秒?见下)。


关于time_t time(0):


time_t被定义为长整型,它返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。比如假设输出:
cout<
值约为1169174701,约等于37(年)乘365(天)乘24(小时)乘3600(秒)(月日没算)。


另外,关于ran_num = rand() % 6,


将rand()的返回值与6求模是必须的,这样才能确保目的随机数落在[0,6)之间,否则rand()的返回值本身可能是很巨大的。
一个通用的公式是:
要取得[a,b)之间的随机整数,使用(rand() % (b-a))+ a (结果值将含a不含b)。
在a为0的情况下,简写为rand() % b。


最后,关于伪随机浮点数:


用rand() / double(RAND_MAX)可以取得0~1之间的浮点数(注意,不同于整型时候的公式,是除以,不是求模),举例:
double ran_numf=0.0;
srand((unsigned)time(0));
for(int i=0;i<10;i++){ 
ran_numf = rand() / (double)(RAND_MAX);
cout<
}
运行结果为:0.716636,0.457725,…等10个0~1之间的浮点数,每次结果都不同。


如果想取更大范围的随机浮点数,比如1~10,可以将
rand() /(double)(RAND_MAX) 改为 rand() /(double)(RAND_MAX/10)
运行结果为:7.19362,6.45775,…等10个1~10之间的浮点数,每次结果都不同。
至于100,1000的情况,如此类推。


以上不是伪随机浮点数最好的实现方法,不过可以将就着用用…
阅读(7652) | 评论(3) | 转发(0) |
0

上一篇:堆和堆排序

下一篇:C++类大小的一些说明

给主人留下些什么吧!~~

iWonderLinux2013-05-31 17:13:53

srand()是用来初始化随机种子数的,因为rand的内部实现是用线性同余法做的,他不是真的随机数,只不过是因为其周期特别长,所以有一定的范围里可看成是随机的,式子: rand = rand*const_1 + c_var; 
srand函数就是给它的第一个rand值。用"int x = rand() % 100;"来生成 0 到 100 之间的随机数这种方法是不可取的, 比较好的做法是: j=(int)(n*rand()/(RAND_MAX+1.0))   产生一个0到n之间的随机数
RAND_MAX=0x7fffffff

iWonderLinux2013-05-31 17:11:06

更重要的一个原因: 
作为伪随机序列产生器的rand()函数,必须具备的一个重要特性就是-》产生的序列必须是可重现的。 这不仅仅是一个算法,相当大的程度上,它关系到代码测试的准确性。如果算法中使用了和rand()的结果相关的数据,通过一个可控的可重现序列,我们就有机会再现每一
次测试的过程,从而更有效的找到问题的所在。 所以这里提出一个建议,代码中,如果rand()的函数结果关系到算法的结果,那么,必须保证你的rand()调用是可重现的。

iWonderLinux2013-05-31 17:10:13

C的函数库之所以没有把使用系统时钟初始化随机种子这步重要的操作直接放进rand函数的实现中,我觉得至少有三个原因: 
(1)可以高效产生连续的随机数,不用每次都初始化; 
(2)给程序员以更高的灵活性,因为可能在要求较高的场合,应该使用更好的的数据做种子,而不是系统时钟; 
(3)对于只是想产生大量伪随机数来尽兴某种验证或者统计,未必需要初始化,大不了程序每次运行都产生同样的一系列随机数而已——有些情况下,这是无所谓的。