JAVA根据权重概率实现抽奖

本文只描述了根据权重实现抽奖的底层工具类


public class LotteryUtil {

    public static void main(String[] args) {
        List<Prize> prizes = new ArrayList<>();

        Prize p2 = new Prize();
        p2.setPrizeName("唇膏");
        p2.setPrizeWeight(5.5);
        prizes.add(p2);

        Prize p3 = new Prize();
        p3.setPrizeName("香水");
        p3.setPrizeWeight(9.8);
        prizes.add(p3);

        Prize p1 = new Prize();
        p1.setPrizeName("眼影");
        p1.setPrizeWeight(4.5);
        prizes.add(p1);

        Prize p4 = new Prize();
        p4.setPrizeName("谢谢参与");
        p4.setPrizeWeight(66);
        prizes.add(p4);

        Prize p5 = new Prize();
        p5.setPrizeName("抽奖次数");
        p5.setPrizeWeight(14.2);
        prizes.add(p5);
        //所有奖品权重总和要等于100
        int[] result = new int[prizes.size()];


        System.out.println("抽奖开始");
        for (int i = 0; i < 1000; i++)// 打印100个测试概率的准确性
        {
            int selected = LotteryUtil.getPrizeIndex(prizes);
            System.out.println("第" + i + "次抽中的奖品为:" + prizes.get(selected).getPrizeName());

            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]);
        System.out.println("抽奖次数:" + result[4]);
    }

    /**
     * 根据Math.random()产生一个double型的随机数,判断每个奖品出现的概率
     *
     * @param prizes
     * @return random:奖品列表prizes中的序列(prizes中的第random个就是抽中的奖品)
     */
    public static int getPrizeIndex(List<Prize> prizes) {
        int random = -1;
        try {
            //计算总权重
            double sumWeight = 0;
            for (Prize p : prizes) {
                sumWeight += p.getPrizeWeight();
            }

            //产生随机数
            double 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).getPrizeWeight())) / sumWeight;
                if ( i == 0 ) {
                    d1 = 0;
                } else {
                    d1 += Double.parseDouble(String.valueOf(prizes.get(i - 1).getPrizeWeight())) / sumWeight;
                }
                if ( randomNumber >= d1 && randomNumber <= d2 ) {
                    random = i;
                    break;
                }
            }
            log.info("getPrizeIndex===>sumWeight:{}--randomNumber:{}--prizes:{}--抽中的奖品是:{}", sumWeight, randomNumber, prizes, prizes.get(random).getPrizeName());
        } catch (Exception e) {
            throw new SimpleException("生成抽奖随机数出错,出错原因:" + e.getMessage());
        }
        return random;
    }


    @Data
    public static class Prize {

        /**
         * 奖品id
         */
        private Long id;

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

        /**
         * 奖品权重
         */
        private double prizeWeight;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值