【项目实战】——Java根据奖品权重计算中奖概率实现抽奖(适用于砸金蛋、大转盘等抽奖活动)


  双蛋节(圣诞+元旦)刚刚过去,前几天项目上线的砸金蛋活动也圆满结束。

这里写图片描述

  现在在许多网站上都会有抽奖的活动,抽奖的算法也是多种多样,这里介绍一下如何根据每种奖品的权重来抽奖,适用于多种抽奖形式。


奖品设置


  比如现在举行一次砸金蛋活动中,奖品如下:

这里写图片描述
   
  奖品够丰富的哇,香车美女豪宅都有了不过由于法律的原因,活人是不能赠送的,所以一等奖只能送海报了~这里写图片描述

  奖品在数据库中的存储情况

这里写图片描述


抽奖实现

  奖品实体 Prize.java

    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()产生一个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,则重新抽取奖品,直到抽到其他奖品位置。


  本来活动期间小编报着随时抢救bug的心态,连回家都抱着电脑,然而从活动上线到活动结束,并没有出现bug在此感谢产品部、测试部和研发部所有同事在上线前轰炸式的测试

这里写图片描述



【 转载请注明出处——胡玉洋《【项目实战】——Java中根据奖品权重实现抽奖(砸金蛋、大转盘等)》

  • 22
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 74
    评论
好的,根据心率、血压和体温等指标来定义权重计算精神压力的公式,以下是一个示例的Java代码: ```java public class MentalStressCalculator { public static void main(String[] args) { int heartRate = 80; // 心率 int bloodPressure = 120; // 血压 double bodyTemperature = 36.5; // 体温 double mentalStress = calculateMentalStress(heartRate, bloodPressure, bodyTemperature); System.out.println("精神压力值: " + mentalStress); } public static double calculateMentalStress(int heartRate, int bloodPressure, double bodyTemperature) { // 根据心率、血压和体温等指标来计算精神压力值的算法 double heartRateWeight = 0.4; // 心率权重 double bloodPressureWeight = 0.3; // 血压权重 double bodyTemperatureWeight = 0.3; // 体温权重 double maxHeartRate = 100; // 心率最大值 double maxBloodPressure = 130; // 血压最大值 double maxBodyTemperature = 37.0; // 体温最大值 // 根据权重和指标值计算精神压力值 double mentalStress = (heartRate / maxHeartRate) * heartRateWeight + (bloodPressure / maxBloodPressure) * bloodPressureWeight + (bodyTemperature / maxBodyTemperature) * bodyTemperatureWeight; return mentalStress; } } ``` 在上述代码中,我们定义了心率、血压和体温的权重,以及它们的最大值。然后,根据权重和指标的实际值,计算精神压力值。你可以根据实际需求调整权重和最大值,并根据具体情况定义更复杂的计算公式。请注意,这只是一个示例,实际情况下可能需要更多的指标和更复杂的算法来准确评估精神压力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 74
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值