白云点缀的蓝 发表于 2021-6-26 12:41

JAVA概率抽奖

礼物奖品类

package com;

import java.math.BigDecimal;

/**
* 奖品类
* @author:rex
* @date:2014年10月20日
* @version:1.0
*/
public class Gift {
       
        private int index;
        private String gitfId;
        private String giftName;
        private double probability;

        public Gift(int index, String gitfId, String giftName, double probability) {
                this.index = index;
                this.gitfId = gitfId;
                this.giftName = giftName;
                this.probability = probability;
        }

        public int getIndex() {
                return index;
        }

        public void setIndex(int index) {
                this.index = index;
        }

        public String getGitfId() {
                return gitfId;
        }

        public void setGitfId(String gitfId) {
                this.gitfId = gitfId;
        }

        public String getGiftName() {
                return giftName;
        }

        public void setGiftName(String giftName) {
                this.giftName = giftName;
        }

        public double getProbability() {
                return probability;
        }

        public void setProbability(double probability) {
                this.probability = probability;
        }

        @Override
        public String toString() {
                return "Gift [礼物索引=" + index + ", 礼物id=" + gitfId + ", 礼物价格=" + giftName + ", 礼物概率="
                                +new BigDecimal(probability+"")+ "]";
        }

}

概率算法类
package com;

;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Random;


public class Lottory {
    private Random rm = new Random();

    public class AwardConfig {
      ///probaility 为概率0.2 即 20% 得概率0.05即5%的中奖概率
      private BigDecimal probaility;
      ///奖品名称
      private String name;

      public BigDecimal getProbaility() {
            return probaility;
      }

      public void setProbaility(BigDecimal probaility) {
            this.probaility = probaility;
      }

      public String getName() {
            return name;
      }

      public void setName(String name) {
            this.name = name;
      }
    }

    public String reward(List<AwardConfig> giftList) {
      if (giftList == null || giftList.isEmpty()) {
            return null;
      }
      // 按照概率排序(如果不排序,下面随机数的区间需要做其他处理,否则无法己算正确的概率分布)
      Collections.sort(giftList, (o1, o2) -> {
            if (o1.getProbaility().doubleValue() > o2.getProbaility().doubleValue()) {
                return 1;
            } else if (o1.getProbaility().doubleValue() == o2.getProbaility().doubleValue()) {
                return 0;
            } else {
                return -1;
            }
      });

      BigDecimal[] probabilityList = new BigDecimal;
      int index = 0;
      BigDecimal allRate = BigDecimal.valueOf(0);
      String targetNumber = "";
      for (AwardConfig gift : giftList) {
            probabilityList = gift.getProbaility();
            allRate = allRate.add(gift.getProbaility());
            index++;
            if (gift.getProbaility().compareTo(BigDecimal.ONE) == 0) {
                /// 如果单个奖品概率等于1,直接中该奖品
                System.out.println("如个奖品概率等于1,直接中该奖品.");
                return gift.getName();
            }
            String proStr = gift.getProbaility().toString();
            String proStrTemp = proStr.substring(proStr.indexOf(".") + 1);
            if (proStrTemp.length() > targetNumber.length()) {
                /// 找到小数位最长的那个概率配置
                targetNumber = proStrTemp;
            }
      }
//      if (allRate.intValue() != 1) {
//            ///这里可以设置 所有奖品得概率总和必须为100%,当然也可以是其他数字,根据区间匹配。
//            System.out.println("概率相加不等于1.");
//            return null;
//      }
      BigDecimal basicNumber = null;
      if (targetNumber != null && targetNumber.equals("") == false) {
            basicNumber = BigDecimal.valueOf(Math.pow(10, targetNumber.length()));
      }
      int diceRoll = rm.nextInt(basicNumber.intValue());
      if (diceRoll < 0) {
            System.err.println("随机数字小于0.");
            return null;
      }
      BigDecimal cumulative = BigDecimal.ZERO;
      for (int i = 0; i < giftList.size(); i++) {
            AwardConfig luckGift = giftList.get(i);
            if (luckGift != null && luckGift.getProbaility().compareTo(BigDecimal.ZERO) > 0) {
                cumulative = cumulative.add(luckGift.getProbaility().multiply(basicNumber));
                ///如果随机出得数字区间落在该奖品得区间内,即中得该奖品。这块得实现可以修改,只要数字区间为奖品区间就可以。
                if (diceRoll <= cumulative.intValue()) {
                  return giftList.get(i).getName();
                }
            }
      }

      return null;
    }

}

主类
package com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* 不同概率抽奖
* @author:rex
* @date:2014年10月20日
* @version:1.0
*/
public class LotteryTest {
        public static void main(List<Gift> gifts,String GiftName,Double probability,Double SubStract) {
               
                gifts = new ArrayList<Gift>();
                // 序号==物品Id==物品名称==概率
//                GiftName="52000";
//                probability=(Double) 0.002;
                gifts.add(new Gift(1, "P1", GiftName, probability));
                gifts.add(new Gift(2, "P2", "没中",(Double)(1-probability)));
//                gifts.add(new Gift(3, "P3", "物品3", 0.4d));
//                gifts.add(new Gift(4, "P4", "物品4", 0.3d));
//                gifts.add(new Gift(5, "P5", "物品5", 0d));
//                gifts.add(new Gift(6, "P6", "物品6", -0.1d));
//                gifts.add(new Gift(7, "P7", "物品7", 0.008d));

                List<Double> orignalRates = new ArrayList<Double>(gifts.size());
                for (Gift gift : gifts) {
                        double probability1 = gift.getProbability();
                        if (probability1 < 0) {
                                probability1 = 0;
                        }
                        orignalRates.add(probability1);
                }
               
                // statistics
                Map<Integer, Integer> count = new HashMap<Integer, Integer>();
                double num = 1;
                for (int i = 0; i < num; i++) {
                        int orignalIndex = LotteryUtil.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()) + ", count=" + entry.getValue() + ", probability="
                                        + entry.getValue() / num));
                        System.out.println(gifts.get(entry.getKey()).getGiftName().equals(GiftName));
                        System.out.println("----------------");
//                                        + entry.getValue() / num));
                }
        }

        public static void main(String[] args) {
                main(new ArrayList<Gift>(),"52000",(Double)0.002,0.01);
        }
}

使用方法,把以上代码放入你所在项目,然后调用main,传入相关参数即可开始抽奖

POJIE1123 发表于 2021-7-9 15:28

学习高端技术

pUcvSEeV58 发表于 2022-2-27 19:48

感谢楼主分享,我瞧瞧

hldcY791 发表于 2022-2-27 20:03

谢谢分享

vpgPGJRwInb 发表于 2022-2-27 20:07

感谢楼主

zBZnSURhcj 发表于 2022-3-1 01:23

感谢楼主

CbsFco13 发表于 2022-3-8 10:31

谢谢分享

rauiM 发表于 2022-3-14 14:28

谢谢分享

AjI9634 发表于 2022-3-14 14:29

威武霸气!

YLa3 发表于 2022-3-14 14:43

感谢楼主
页: [1] 2 3 4 5 6 7
查看完整版本: JAVA概率抽奖