Java抽奖概率算法


奖品

在这里插入图片描述

实体

package com.leigq.www.shiro.controller;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

/** * 奖品 DTO * <br/> * * @author :leigq * @date :2019/7/5 23:00 */
@Data
@Builder
@AllArgsConstructor
public class GiftDTO {

    /** * 索引 */
    private Integer index;


    /** * 奖品名称 */
    private String name;

    /** * 奖品编号 */
    private String no;


    /** * 中奖概率 */
    private Double probability;
}

抽奖方法

 /** * 抽奖方法 * <br/> * create by: leigq * <br/> * create time: 2019/7/5 23:08 * @param orignalRates 商品中奖概率列表,保证顺序和实际物品对应 * @return 中奖商品索引 */
 public static int lottery(List<Double> orignalRates) {

     if (orignalRates == null || orignalRates.isEmpty()) {
         return -1;
     }

     int size = orignalRates.size();

     // 计算总概率,这样可以保证不一定总概率是1
     double sumRate = 0d;
     for (double rate : orignalRates) {
         sumRate += rate;
     }

     // 计算每个物品在总概率的基础下的概率情况
     List<Double> sortOrignalRates = new ArrayList<>(size);
     Double tempSumRate = 0d;
     for (double rate : orignalRates) {
         tempSumRate += rate;
         sortOrignalRates.add(tempSumRate / sumRate);
     }

     // 根据区块值来获取抽取到的物品索引
     double nextDouble = Math.random();
     sortOrignalRates.add(nextDouble);
     Collections.sort(sortOrignalRates);

     return sortOrignalRates.indexOf(nextDouble);
 }

测试

我这里就只用两个商品测试

public static void main(String[] args) {

    List<GiftDTO> gifts = new ArrayList<>();
    gifts.add(new GiftDTO(1,  "一等奖", "P1", 0.4d));
    gifts.add(new GiftDTO(2, "谢谢参与","P2", 0.6d));

    // 存储概率
    List<Double> orignalRates = new ArrayList<>(gifts.size());
    for (GiftDTO gift : gifts) {
        double probability = gift.getProbability();
        if (probability < 0) {
            probability = 0;
        }
        orignalRates.add(probability);
    }

    // 统计
    Map<Integer, Integer> count = new HashMap<>();

    // 测试次数
    double num = 1000000;
    for (int i = 0; i < num; i++) {
        int orignalIndex = lottery(orignalRates);
        Integer value = count.get(orignalIndex);
        count.put(orignalIndex, value == null ? 1 : value + 1);
    }

    for (Map.Entry<Integer, Integer> entry : count.entrySet()) {
        System.out.println(gifts.get(entry.getKey()) + ", 命中次数=" + entry.getValue() + ", 实际概率="
                + entry.getValue() / num);
    }
}

在这里插入图片描述
结果与预期差不多。

感谢


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM