您的位置:首页 > 其它

一种不等概率随机数产生办法

2009-02-03 23:47 603 查看
一种不等概率随机数产生办法

Java实用工具库Java.util中的Random提供了产生各种类型随机的方法,它可以产生int,long,float,double等类型的随机数。例如:

Random rd = new Random();
System.out.println("The set of random numbers:");
System.out.println("Integer:"+rd.nextInt());
System.out.println("Long:"+rd.nextLong());
System.out.println("Float:"+rd.nextFloat());
System.out.println("Double:"+rd.nextDouble());


运行结果:

The set of random numbers:
Integer:15731478
Long:-6685918349244253815
Float:0.45258975
Double:0.7963162839600346


下面来说说等概率随机数产生办法,其实这个很简单,如下函数就已经轻松实现了获得0--max-1之内的等概率随机整数:

private static int getRandInt(int max){
Random rd = new Random();
return Math.abs(rd.nextInt()%max);
}


在J2ME手机游戏开发中,经常会使用这种方式获得等概率随机整数。

但是有时在游戏编程中,我们可能需要所获取的随机数概率并不相同,比方说从怪物身上掉落的装备的概率往往是级别愈高,掉落的愈低,反正则愈高。好了让我来把问题抽象为如下编程任务:假定需要产生0到n之间(包括0和n)的随机数,并且要求产生0的概率最大,1次之,2又比1次之,以此类推,n的概率最低。问题清楚了,那么就来考虑一下算法问题,为简单起见,我让产生各个数字的概率等差递减,也就是说,各个随机数的概率之比为:n+1:n:n-1:n-2:......1,那么首先要构造一个区间,区间的下限为0,上限为各个比例数字之和,也就是(n+1)+n+(n-1)+......+1。那么,构造这样一个区间有什么用呢?首先把这个大区间划分为n+1个长度不等的区间,每个小区间的跨度和各个数字的产生概率对应,也就是[0,n](跨度为n+1),[n+1,2n](跨度为n),以此类推,因此这些小区间就代表了各个数字产生的概率。最后在大区间中生成一个等概率随机数x,x落在哪个小区间内,那么就产生代表该区间的那个数字。产生等差递减概率的随机数的思路有了,那么下面的代码就不难理解了:

//获得0--n之内的不等概率随机整数,0概率最大,1次之,以此递减,n最小
private static int getAnyRandInt(int n){
int max = n+1;
int bigend = ((1+max)*max)/2;
Random rd = new Random();
int x = Math.abs(rd.nextInt()%bigend);
int sum = 0;
for(int i = 0; i<max; i++){
sum += (max - i);
if(sum>x){
return i;
}
}
return -1;
}


最后给出我写得一个等概率随机数与不等概率随机数测试与验证程序代码:

import java.util.*;

public class RandomTest {
public static void main(String[] args){
Random ran1 = new Random();
Random ran2 = new Random(12345);

System.out.println("The 1st set of random numbers:");
System.out.println("Integer:"+ran1.nextInt());
System.out.println("Long:"+ran1.nextLong());
System.out.println("Float:"+ran1.nextFloat());
System.out.println("Double:"+ran1.nextDouble());

System.out.println("The 2nd set of random numbers:");
for(int i = 0; i<20; i++){
if(i%5 == 0){
System.out.println();
}
System.out.print(ran2.nextInt()+ " ");
}

int[] rate = new int[10];
System.out.println();
int n = 0;
for(int i = 0; i<200; i++){
if(i%40 == 0){
System.out.println();
}
n = getRandInt(10);
rate
++;
System.out.print(n+ " ");
}

displayRandRate(rate, "getRandInt等概率随机数0--9依次出现次数:");

Arrays.fill(rate, 0);
for(int i = 0; i<200; i++){
if(i%40 == 0){
System.out.println();
}
n = getAnyRandInt(9);
rate
++;
System.out.print(n+ " ");
}

displayRandRate(rate, "getAnyRandInt不等概率随机数0--9依次出现次数:");
}

//获得0--max-1之内的等概率随机整数
private static int getRandInt(int max){
Random rd = new Random();
return Math.abs(rd.nextInt()%max);
}

//获得0--n之内的不等概率随机整数,0概率最大,1次之,以此递减,n最小
private static int getAnyRandInt(int n){
int max = n+1;
int bigend = ((1+max)*max)/2;
Random rd = new Random();
int x = Math.abs(rd.nextInt()%bigend);
int sum = 0;
for(int i = 0; i<max; i++){
sum += (max - i);
if(sum>x){
return i;
}
}
return -1;
}

private static void displayRandRate(int rate[], String description){
System.out.println();
System.out.println();
System.out.println(description);
for(int i = 0; i<rate.length; i++){
System.out.print(rate[i]+ " ");
}
System.out.println();
}
}


最后给出该程序某次运行的结果:

The 1st set of random numbers:
Integer:-158150616
Long:8776385264218048298
Float:0.22843891
Double:0.6794943450281173

The 2nd set of random numbers:

1553932502 -2090749135 -287790814 -355989640 -716867186
161804169 1402202751 535445604 1011567003 151766778
1499439034 -51321412 1924478780 -370025683 -1554121271
496460768 679749574 -301730690 -992618231 1128070351

7 7 5 8 8 6 9 5 6 4 5 4 3 8 2 2 3 1 4 0
2 4 9 9 6 5 4 6 1 4 4 0 3 8 8 7 4 2 6 6
3 1 7 8 5 1 0 3 9 4 8 6 1 5 7 7 7 8 0 9
7 1 2 4 4 5 8 1 9 0 7 0 8 2 4 7 9 1 6 7
4 8 9 4 4 5 2 0 2 5 2 3 4 2 2 9 1 4 7 6
3 4 8 5 6 6 2 9 1 4 7 2 6 1 8 5 7 4 0 1
8 2 9 4 9 3 3 6 2 8 2 6 5 0 9 3 4 6 0 1
8 6 7 8 7 6 7 0 0 9 5 8 2 6 5 7 2 5 1 3
9 8 7 4 7 2 2 3 1 0 4 2 0 6 1 1 4 7 4 0
2 8 8 9 6 6 2 1 5 2 4 9 2 6 3 1 3 2 9 5

getRandInt等概率随机数0--9依次出现次数:
15 19 26 14 27 17 22 21 21 18

2 5 6 9 5 2 1 3 0 4 2 4 2 8 1 3 5 0 5 7
2 2 8 5 4 9 8 0 2 0 8 0 0 2 0 2 9 5 0 0
2 3 1 5 0 2 1 4 2 0 7 1 0 5 8 4 3 3 7 7
3 1 3 0 3 3 3 0 0 6 1 1 0 0 6 0 4 6 5 9
2 0 0 4 2 6 1 3 7 2 0 1 1 3 5 1 0 4 0 4
2 7 0 3 6 0 6 2 7 0 9 5 3 0 2 8 5 9 1 1
1 0 5 3 4 2 5 2 1 1 4 2 2 7 7 2 8 5 0 4
8 1 2 3 4 3 1 4 6 5 3 2 2 9 6 0 0 1 2 5
2 9 6 2 2 2 0 2 6 5 6 8 0 0 0 1 0 3 2 6
3 7 5 2 2 1 0 3 0 2 1 0 2 7 2 4 1 3 7 3

getAnyRandInt不等概率随机数0--9依次出现次数:
39 24 38 23 15 19 13 12 9 8

by Loomman, QQ:28077188, MSN: Loomman@hotmail.com QQ裙:30515563 ☆程序天堂☆ 请尊重作者原创,转载注明来自裂帛一剑博客,谢谢合作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: