Java根据奖品权重计算中奖概率实现抽奖
2017-03-23 10:29
627 查看
现在在许多网站上都会有抽奖的活动,抽奖的算法也是多种多样,这里介绍一下如何根据每种奖品的权重来抽奖,适用于多种抽奖形式。
实体:
public class Prize {
private int id;//奖品id
private String prize_name;//奖品名称
private int prize_amount;//奖品(剩余)数量
private int prize_weight;//奖品权重
//getter、setter
这里只考虑最简单的抽奖实现,所以暂时只为奖品设计如上4个字段。
见注释,prize_name表示奖品名称;prize_amount表示奖品数量,即本次抽奖活动计划发放此奖品的数量;prize_weight表示奖品权重,表示奖品被抽到的几率的比重,权重越大,被抽到的几率越大,比如本次砸金蛋活动有4种奖品,权重分别是1、2、3、4,总权重是10,那么每种奖品被抽到的几率就是1/10,2/10,3/10,4/10。
核心算法:
/**
* 根据Math.random()产生
a8f9
一个double型的随机数,判断每个奖品出现的概率
* @param prizes
* @return random:奖品列表prizes中的序列(prizes中的第random个就是抽中的奖品)
*/
public int getPrizeIndex(List<Prize> prizes) {
DecimalFormat df = new DecimalFormat("######0.00");
int random = -1;
try{
//计算总权重
double sumWeight = 0;
for(Prize p : prizes){
sumWeight += p.getPrize_weight();
}
//产生随机数
double randomNumber;
randomNumber = Math.random();
//根据随机数在所有奖品分布的区域并确定所抽奖品
double d1 = 0;
double d2 = 0;
for(int i=0;i<prizes.size();i++){
d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrize_weight()))/sumWeight;
if(i==0){
d1 = 0;
}else{
d1 +=Double.parseDouble(String.valueOf(prizes.get(i-1).getPrize_weight()))/sumWeight;
}
if(randomNumber >= d1 && randomNumber <= d2){
random = i;
break;
}
}
}catch(Exception e){
System.out.println("生成抽奖随机数出错,出错原因:" +e.getMessage());
}
return random;
}
抽奖的逻辑可以用下面这张图表示:
分析:如上图,为了便于计算和理解,设置每种奖品的权重分别为1,2,3,4,所以被抽到的概率分别为0.1,0.2,0.3,0.4(本次活动中奖概率为100%)。
先生成一个随机数randomNumber,然后根据随机数所处区域判断奖品:
0<randomNumber<=0.1 表示抽中一等奖
0.1<randomNumber<=0.3 表示抽中二等奖
0.3<randomNumber<=0.6 表示抽中三等奖
0.6<randomNumber<=1.0 表示抽中四等奖
抽奖测试
public static void main(String[] agrs) {
int i = 0;
PrizeMathRandom a = new PrizeMathRandom();
int[] result=new int[4];
List<Prize> prizes = new ArrayList<Prize>();
Prize p1 = new Prize();
p1.setPrize_name("范冰冰海报");
p1.setPrize_weight(1);//奖品的权重设置成1
prizes.add(p1);
Prize p2 = new Prize();
p2.setPrize_name("上海紫园1号别墅");
p2.setPrize_weight(2);//奖品的权重设置成2
prizes.add(p2);
Prize p3 = new Prize();
p3.setPrize_name("奥迪a9");
p3.setPrize_weight(3);//奖品的权重设置成3
prizes.add(p3);
Prize p4 = new Prize();
p4.setPrize_name("双色球彩票");
p4.setPrize_weight(4);//奖品的权重设置成4
prizes.add(p4);
System.out.println("抽奖开始");
for (i = 0; i < 10000; i++)// 打印100个测试概率的准确性
{
int selected=a.getPrizeIndex(prizes);
System.out.println("第"+i+"次抽中的奖品为:"+prizes.get(selected).getPrize_name());
result[selected]++;
System.out.println("--------------------------------");
}
System.out.println("抽奖结束");
System.out.println("每种奖品抽到的数量为:");
System.out.println("一等奖:"+result[0]);
System.out.println("二等奖:"+result[1]);
System.out.println("三等奖:"+result[2]);
System.out.println("四等奖:"+result[3]);
}
尝试抽奖10000次的结果如下:
每类奖品获奖次数比例刚好大约为1:2:3:4,学过概率的你肯定知道抽奖次数越多,测试结果越准确~~
Tips:
如果计划中奖率是100%的话,那么10个奖品只能抽奖10次,所以还要根据实际情况设置每种奖品数量和权重。
如果需要设置中奖率不为100%,可以添加一个“伪奖品”,并为其设置权重,那么抽到这个“伪奖品”的概率就是不中奖的概率。
如果在抽奖过程中某类奖品抽完了,可以做个判断,如果此奖品的剩余数量为0,则重新抽取奖品,直到抽到其他奖品位置。
实体:
public class Prize {
private int id;//奖品id
private String prize_name;//奖品名称
private int prize_amount;//奖品(剩余)数量
private int prize_weight;//奖品权重
//getter、setter
这里只考虑最简单的抽奖实现,所以暂时只为奖品设计如上4个字段。
见注释,prize_name表示奖品名称;prize_amount表示奖品数量,即本次抽奖活动计划发放此奖品的数量;prize_weight表示奖品权重,表示奖品被抽到的几率的比重,权重越大,被抽到的几率越大,比如本次砸金蛋活动有4种奖品,权重分别是1、2、3、4,总权重是10,那么每种奖品被抽到的几率就是1/10,2/10,3/10,4/10。
核心算法:
/**
* 根据Math.random()产生
a8f9
一个double型的随机数,判断每个奖品出现的概率
* @param prizes
* @return random:奖品列表prizes中的序列(prizes中的第random个就是抽中的奖品)
*/
public int getPrizeIndex(List<Prize> prizes) {
DecimalFormat df = new DecimalFormat("######0.00");
int random = -1;
try{
//计算总权重
double sumWeight = 0;
for(Prize p : prizes){
sumWeight += p.getPrize_weight();
}
//产生随机数
double randomNumber;
randomNumber = Math.random();
//根据随机数在所有奖品分布的区域并确定所抽奖品
double d1 = 0;
double d2 = 0;
for(int i=0;i<prizes.size();i++){
d2 += Double.parseDouble(String.valueOf(prizes.get(i).getPrize_weight()))/sumWeight;
if(i==0){
d1 = 0;
}else{
d1 +=Double.parseDouble(String.valueOf(prizes.get(i-1).getPrize_weight()))/sumWeight;
}
if(randomNumber >= d1 && randomNumber <= d2){
random = i;
break;
}
}
}catch(Exception e){
System.out.println("生成抽奖随机数出错,出错原因:" +e.getMessage());
}
return random;
}
抽奖的逻辑可以用下面这张图表示:
分析:如上图,为了便于计算和理解,设置每种奖品的权重分别为1,2,3,4,所以被抽到的概率分别为0.1,0.2,0.3,0.4(本次活动中奖概率为100%)。
先生成一个随机数randomNumber,然后根据随机数所处区域判断奖品:
0<randomNumber<=0.1 表示抽中一等奖
0.1<randomNumber<=0.3 表示抽中二等奖
0.3<randomNumber<=0.6 表示抽中三等奖
0.6<randomNumber<=1.0 表示抽中四等奖
抽奖测试
public static void main(String[] agrs) {
int i = 0;
PrizeMathRandom a = new PrizeMathRandom();
int[] result=new int[4];
List<Prize> prizes = new ArrayList<Prize>();
Prize p1 = new Prize();
p1.setPrize_name("范冰冰海报");
p1.setPrize_weight(1);//奖品的权重设置成1
prizes.add(p1);
Prize p2 = new Prize();
p2.setPrize_name("上海紫园1号别墅");
p2.setPrize_weight(2);//奖品的权重设置成2
prizes.add(p2);
Prize p3 = new Prize();
p3.setPrize_name("奥迪a9");
p3.setPrize_weight(3);//奖品的权重设置成3
prizes.add(p3);
Prize p4 = new Prize();
p4.setPrize_name("双色球彩票");
p4.setPrize_weight(4);//奖品的权重设置成4
prizes.add(p4);
System.out.println("抽奖开始");
for (i = 0; i < 10000; i++)// 打印100个测试概率的准确性
{
int selected=a.getPrizeIndex(prizes);
System.out.println("第"+i+"次抽中的奖品为:"+prizes.get(selected).getPrize_name());
result[selected]++;
System.out.println("--------------------------------");
}
System.out.println("抽奖结束");
System.out.println("每种奖品抽到的数量为:");
System.out.println("一等奖:"+result[0]);
System.out.println("二等奖:"+result[1]);
System.out.println("三等奖:"+result[2]);
System.out.println("四等奖:"+result[3]);
}
尝试抽奖10000次的结果如下:
一等奖:962 二等奖:2007 三等奖:3043 四等奖:3988
每类奖品获奖次数比例刚好大约为1:2:3:4,学过概率的你肯定知道抽奖次数越多,测试结果越准确~~
Tips:
如果计划中奖率是100%的话,那么10个奖品只能抽奖10次,所以还要根据实际情况设置每种奖品数量和权重。
如果需要设置中奖率不为100%,可以添加一个“伪奖品”,并为其设置权重,那么抽到这个“伪奖品”的概率就是不中奖的概率。
如果在抽奖过程中某类奖品抽完了,可以做个判断,如果此奖品的剩余数量为0,则重新抽取奖品,直到抽到其他奖品位置。
相关文章推荐
- 【项目实战】——Java根据奖品权重计算中奖概率实现抽奖(适用于砸金蛋、大转盘等抽奖活动)
- 根据概率抽奖(无奖品数量) -- Java实现
- Java根据概率、剩余奖品数量动态抽奖算法实现,概率总和可以不为100%
- Java 实现根据权重设置抽奖概率
- php实现可以设置中奖概率的抽奖程序代码分享
- 黑马程序员 Java中根据YYYY-MM-DD格式的日期计算为星期几的两种实现方式
- php实现自定义中奖项数和概率的抽奖函数示例
- 基于PHP代码实现中奖概率算法可用于刮刮卡、大转盘等抽奖算法
- 6、基于highcharts实现的线性拟合,计算部分在java中实现,画的是正态概率图
- java实现一个抽奖概率类
- 6、基于highcharts实现的线性拟合,计算部分在java中实现,画的是正态概率图
- C#&PHP&Java实现Alias Method概率抽奖算法
- js 计算奖品概率抽奖
- java根据概率随机中奖 测试类
- 根据经纬度计算两地距离java实现
- Java中使用LocalDate根据日期来计算年龄的实现方法
- java版根据权重抽奖算法
- HMM的概率计算问题和预测问题的java实现
- 根据两点经纬度计算距离和角度——java实现
- Java实现根据权重优先返回(速度较快)