第1讲已经详细介绍了rand()如何生成随机数的方法和基本原理。本讲我们介绍一些常见均匀随机量的生成方法:
一、闭区间[0, 1]上等概率随机小数的生成
x1 = rand()/(RAND_MAX+0.0) ,则x1~U[0,1]。
如果是开区间(0, 1),则x2 = (rand()+1)/(RAND_MAX+2.0)。
如果是半开半闭区间[0,1),则x3 = rand()/(RAND_MAX+1.0); 或者区间(0, 1],则x4 = (rand()+1)/(RAND_MAX+1.0)。
说明:1.这样生成的随机小数之间最小间隔为1.0/RAND_MAX(0至1之间最多分布RAND_MAX个不同的数);
2.如果我们要提高均匀随机小数的分布密度,可以这样:x' = (rand()+rand()+...+rand())/(n*RAND_MAX+0.0),前面分子的rand()有n个,注意一定要离散写,因为每个rand()都是独立生成的不同随机数。
二、闭区间[float a, float b]上等概率随机浮点数的生成
利用上面的结论,很容易知道x = x1 * float(b-a)+a ,即x~U[a,b]。
区间为(a, b),[a, b)或(a, b]可同理推导。
说明:如果(b-a)的值很大,即a,b之间间隔很大,由于生成的所有x之间最小间隔为float(b-a)/RAND_MAX,例如如果a=0,b=RAND_MAX,则x = 0,1,2,...,RAND_MAX。所以为了提高生成的随机浮点数的分布密度,我们可以用上面的方法,即 x = x' * float(b-a)+a 。
三、闭区间[int a, int b]上等概率随机整数的生成
利用第一、第二的结论,生成[a, b]上等概率随机整数的公式为:k = int(x3 * float(b+1-a)+a),其中x3~U[0, 1),该方法先生成[a, b+1)上的均匀随机浮点数,然后取整,这样[a,a+1)上的浮点数取整为a,[a+1,a+2)上的浮点数取整为a+1,...,[b,b+1)上的浮点数取整为b,保证了可以得到[a, b]上所有随机整数,且取每一个的概率都相同。
当(b-a)的值很大,即a,b之间间隔很大,同理可以用“第二”的方法提高随机分布“均匀性”!
说明:这个地方网上很多教程给的公式都是k = rand()%(b-a+1)+a,这样是不严密的!!!仅仅当(b-a)远远小于RAND_MAX时,该方法可行;但是当(b-a)比较大,例如a=0,b=20000时,这样产生的随机整数并不是“等概率”的。为什么呢?因为rand()产生的随机整数为0~RAND_MAX(=32767),整数0和20000生成的概率就不一样,rand()为0和20001时,生成的随机数都是0,但是生成整数20000却仅当rand()=20000,很明显生成0和20000的概率不相等!!!(楼主亲测)
四、三维空间沿任意方向等概率单位随机向量N = {x,y,z}的生成
float x,y,z,length;
while(1)
{
x = -1+2*rand()/(RAND_MAX+0.0);
y = -1+2*rand()/(RAND_MAX+0.0);
z = -1+2*rand()/(RAND_MAX+0.0);
if((length=x*x+y*y+z*z)<=1) //Notice this!
break;
}
length = sqrt(length);
float N[3] = {x/length,y/length,z/length};
上图为空间一个包围单位球的单位立方体,生成的单位随机向量可以沿球上任何方向。如果要生成n维单位随机向量,只需将上面代码推广到n个指标!
这一讲就到此结束,第三讲讨论不等概率随机量的生成!!!