公司最近市场活动需求频繁更新 什么抽奖活动 大转盘 摇一摇 各种活动 活动类型各种各样但是都是通过概率去算出来是否中将废话不多说 新手上路 大神勿喷
实体类
public class AnniversaryPrizePool {
//序号
private int index;
//中奖概率
private BigDecimal winningProbability;
//奖品Id
private Integer prizeId;
//奖品名称
private String giftName;
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public BigDecimal getWinningProbability() {
return winningProbability;
}
public void setWinningProbability(BigDecimal winningProbability) {
this.winningProbability = winningProbability;
}
public Integer getPrizeId() {
return prizeId;
}
public void setPrizeId(Integer prizeId) {
this.prizeId = prizeId;
}
public String getGiftName() {
return giftName;
}
public void setGiftName(String giftName) {
this.giftName = giftName;
}
public AnniversaryPrizePool(int index, BigDecimal winningProbability, Integer prizeId, String giftName) {
this.index = index;
this.winningProbability = winningProbability;
this.prizeId = prizeId;
this.giftName = giftName;
}
@Override
public String toString() {
return "AnniversaryPrizePool{" +
"index=" + index +
", winningProbability=" + winningProbability +
", prizeId=" + prizeId +
", giftName='" + giftName + '\'' +
'}';
}
核心算法
/**
* 抽奖
* @param anniversaryPrizePools 原始的概率列表,保证顺序和实际物品对应
* @return 物品的索引
*/
public static int lottery(List anniversaryPrizePools) {
//扩大倍数
int mulriple = 100;
BigDecimal now = BigDecimal.ZERO;
for (AnniversaryPrizePool anniversaryPrizePool : anniversaryPrizePools) {
//所有概率加起来
now = now.add(anniversaryPrizePool.getWinningProbability());
}
//概率乘以倍数
mulriple = now.multiply(new BigDecimal(mulriple)).intValue();
int lastScope = 0;
// 洗牌,打乱奖品次序
Collections.shuffle(anniversaryPrizePools);
Map prizeScopes = new HashMap();
for (AnniversaryPrizePool anniversaryPrizePool : anniversaryPrizePools) {
int prizeId = anniversaryPrizePool.getPrizeId();
// 划分区间
int currentScope = lastScope + anniversaryPrizePool.getWinningProbability().multiply((new BigDecimal(mulriple).divide(now,0,BigDecimal.ROUND_HALF_UP))).intValue();
prizeScopes.put(prizeId, new int[] { lastScope + 1, currentScope });
lastScope = currentScope;
}
//获得随机的概率
int luckyNumber = new Random().nextInt(mulriple);
int luckyPrizeId = 0;
// 查找随机数所在的区间
if ((null != prizeScopes) && !prizeScopes.isEmpty()) {
Set> entrySets = prizeScopes.entrySet();
for (Map.Entry m : entrySets) {
int key = m.getKey();
if (luckyNumber >= m.getValue()[0] && luckyNumber <= m.getValue()[1]) {
luckyPrizeId = key;
break;
}
}
}
return luckyPrizeId;
}
算法实现
首先把所有的商品中间的概率相加然后扩大多少倍我这里是扩大一百倍 扩大倍数可以根据自己的需求去扩大 然后打乱次序
然后获取随机数划分区间
看测试
public static void main(String[] args) {
List anniversaryPrizePoolsList = new ArrayList();
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(1, new BigDecimal(0.4), 1, "再来一次"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(2, new BigDecimal(0.3), 3, "本站VIP一年"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(3, new BigDecimal(0.5), 0, "谢谢参与"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(4, new BigDecimal(0.2), 5, "50金币"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(5, new BigDecimal(0.1), 6, "Iphone 6"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(6, new BigDecimal(0), 7, "Ipad Air2"));
anniversaryPrizePoolsList.add(new AnniversaryPrizePool(7, new BigDecimal(0), 8, "100元手机话费"));
double num = 100;
int index = 0;
int indexs = 0;
for (int i = 0; i < num; i++) {
int lottery = LotteryUtil.lottery(anniversaryPrizePoolsList);
index = index + 1;
}
System.out.println("第" + index + "抽奖");
System.out.println("谢谢参与次数为:"+indexs);
}
所谓概率不是百分百精准 也就是说众生平等 这里这概率设置为0的就怎么抽都抽不到
既然说到了概率不会是百分百精准 在实际场景中我们的商品还有一个库存的概念也就是说你中奖了但是库存不足也会是谢谢参与