2024年4月30日发(作者:)
自己领悟把
一.计算机中随机数的产生
现在,在计算机,用来产生随机数的算法是“线性同余”法。所谓线性同余,其实就是下面两个式子。
假设I就是一个随机数的序列,Ij+1与Ij的关系如下:
Ij+1 =Ij * a+c (mod m)
或是Ij+1 =Ij *a (mod m),
其中,不妨取a=16807,m=2147483647,以为一常数。写个简单的程序就是:
long r;
void scand( long v)//初始化随机种子数
{
r = v;
}
long rand()//产生随机数
{
r = (r*a + c)%m;//a,c,m为常数
return r;
}
再看一下稍复杂一点的:(Random () 的 Borland 的实现)
long long RandSeed = #### ;
unsigned long Random(long max)
{
long long x ;
double i ;
unsigned long final ;
x = 0xffffffff;
x += 1 ;
RandSeed *= ((long long)134775813);
RandSeed += 1 ;
RandSeed = RandSeed % x ;
i = ((double)RandSeed) / (double)0xffffffff ;
final = (long) (max * i) ;
return (unsigned long)final;
}
二.计算机产生的随机数不是真的随机数
[引:]我们建立了真正调用伪随机数生成器的 random()。但什么是伪随机数生成器?假定需要生成介
于 1 和 10 之间的随机数,每一个数出现的几率都是一样的。理想情况下,应生成 0 到 1 之间的
一个值,不考虑以前值,这个范围中的每一个值出现的几率都是一样的,然后再将该值乘以 10。请
注意,在 0 和 1 之间有无穷多个值,而计算机不能提供这样的精度。
为了编写代码来实现类似于前面提到的算法,常见情况下,伪随机数生成器生成 0 到 N 之间的一
个整数,返回的整数再除以 N。得出的数字总是处于 0 和 1 之间。对生成器随后的调用采用第一
次运行产生的整数,并将它传给一个函数,以生成 0 到 N 之间的一个新整数,然后再将新整数除
以 N 返回。这意味着,由任何伪随机数生成器返回的数目会受到 0 到 N 之间整数数目的限制。
在大多数的常见随机数发生器中,N 是 232? (大约等于 40 亿),对于 32 位数字来说,这是最
大的值。换句话说,我们经常碰到的这类生成器能够至多生成 40 亿个可能值。而这 40 亿个数根
本不算大,只是指尖这么大。
伪随机数生成器将作为“种子”的数当作初始整数传给函数。这粒种子会使这个球(生成伪随机数)一
直滚下去。伪随机数生成器的结果仅仅是不可预测。由伪随机数生成器返回的每一个值完全由它返回
的前一个值所决定(最终,该种子决定了一切)。如果知道用于计算任何一个值的那个整数,那么就
可以算出从这个生成器返回的下一个值。
结果,伪随机数生成器是一个生成完全可预料的数列(称为流)的确定性程序。一个编写得很好的的
PRNG 可以创建一个序列,而这个序列的属性与许多真正随机数的序列的属性是一样的。例如:
PRNG 可以以相同几率在一个范围内生成任何数字。
PRNG 可以生成带任何统计分布的流。
由 PRNG 生成的数字流不具备可辨别的模式。
PRNG 所不能做的是不可预测。如果知道种子和算法,就可以很容易地推算出这个序列。
计算机产生的随机数一般都只是一个周期很长的数列,不是真的随机数。也就是说,随机数一般是伪
随机数,每个随机数都是由随机种子开始的一个已定的数列(周期很长)。一般地,为了随机数更真
一点,随机种子在系统中通常是参照系统时钟生成的。
看看下面这个例子,从中,读者应能有所体会。
main()
{
int i;
scand(time(NULL)); /*可向计算机读取其时钟值,并把值自动设为随机数种子*/
for(i=0;i<10;i++){
printf("%10d",1+(rand()%6));/*这里1是移动值,他等于所需的连续整数*/
} /*数值范围的第一个数;b是比例因子;他*/
return(0); /*等于所需的连续整数值的范围宽度;*/
}
从数学上讲,为了得到一个周期性更长的随机序列,我们可以使用如下方法:(这是我在一个书上看
到的,详细的情况大家可以查一查,我自己也记不清了,呵呵)
float rand(long* idum)
{
int j; long k; static long iy=0; static long iv[NTAB];
float temp;
if(*idum<=0||!iy)
{
if(-(*idum)<1) *idum=1;
else *idum=-(*idum);
for(j=NTAB+7;j>=0;j--){
k=(*idum)/IQ;
*idum=IA*(*idum-k*IQ)-k*IR;
if(*idum<0)
*idum+=IM;
发布者:admin,转转请注明出处:http://www.yc00.com/web/1714492618a2456996.html
评论列表(0条)