怎么样能够产生不等概率随机数?
在编写程序的时候,经常要用到随机数。JAVA自带了一个产生随机数的方法,该方法能够较好的等概率的产生某个区间之内的随机数。但是有些时候,我们需要在一个区间内产生不等概率的随机数。比如一个数组,我想随机的取出一个元素,如果元素靠前则取出的概率大些,如果元素靠后则取出的概率小些,这里就要用到不等概率随机数来作为数组的下标来从数组中取出数字。下面我们就来探讨一个简单的算法。我们先把问题叙述的更详细一点,就是在一个[0, n]的区间中,产生一个随机数,0的概率最大,1的概率比0稍小,2的概率比1稍小,以此类推,产生n的概率是最小的,这就是所谓的不等概率随机数。
问题叙述清楚了,下面说说算法。我们简单起见,让产生各个数字的概率等差递减,也就是说,各个随机数的概率之比为“n+1:n:n-1:……1”。那么,我们首先要构造一个区间,区间的下限为0,上限为各个比率数字之和,也就是(n+1)+n+(n-1)+(n-2)+……+1。那么,构造这样一个区间有什么用呢?我们首先把这个大区间划分为n+1个长度不等的小区间,每个小区间的跨度和各个数字的产生概率对应,也就是[0, n](跨度为n+1),[n+1, 2n](跨度为n),以此类推。因此,这些小区间就代表了各个数字产生的概率。最后在大区间中生成一个等概率随机数x,x落在哪个小区间内,那么就产生该区间代表的那个数字。算法大概就是这样,下面给出一个具体的实现:
//产生0~n之间的随机数,0的概率最大,n的概率最小
privatestaticintmyRandom(intn){
intmax=n+1;//0~n共有n+1个数字
intbigend=((1+max)*max)/2;//大区间的上限(1+2+……+max)
intx=(int)(Math.random()*bigend);//产生一个区间内的随机数x
intsum=0;//sum表示了各个小区间的上限
for(inti=0;i<max;i++){
sum+=(max-i);//sum每次增长的长度为各个小区间的跨度
if(sum>x)//如果sum>x,就表明x落在了第i个小区间内
returni;//因此,i就是我们要产生的随机数
}
return-1;
}
privatestaticintmyRandom(intn){
intmax=n+1;//0~n共有n+1个数字
intbigend=((1+max)*max)/2;//大区间的上限(1+2+……+max)
intx=(int)(Math.random()*bigend);//产生一个区间内的随机数x
intsum=0;//sum表示了各个小区间的上限
for(inti=0;i<max;i++){
sum+=(max-i);//sum每次增长的长度为各个小区间的跨度
if(sum>x)//如果sum>x,就表明x落在了第i个小区间内
returni;//因此,i就是我们要产生的随机数
}
return-1;
}
本文地址:http://www.45fan.com/a/question/67682.html