java實現抽獎概率類
阿新 • • 發佈:2020-11-27
本文例項為大家分享了java實現抽獎概率類的具體程式碼,供大家參考,具體內容如下
在一些專案需求中,可能會遇到抽獎問題,如提供一系列獎品及獲獎概率,要求根據概率返回每次抽到的獎品。以下是本人在實際專案中寫的一個抽獎工具類,與大家共同分享:
import java.util.ArrayList; import java.util.List; import java.util.Random; /** * 抽獎工具類,概率和可以不等於1 * 概率為百分數去掉百分號的部分,如10%,則為10 * 抽獎操作如下: * 1.輸入抽獎概率集合,【抽獎概率集合為{10.0,20.0,30.0}】 * 2.生成連續集合, 【生成的連續集合為{(0.0,10.0],(10.0,30.0],(30.0,60.0]}】 * 3.生成隨機數, 【生成方法為 random.nextDouble() * maxElement】 * 4.判斷隨機數在哪個區間內,返回該區間的index【生成了隨機數12.001,則它屬於(10.0,30.0],返回 index = 1】 * */ public class LotteryUtil { /** * 定義一個連續集合 * 集合中元素x滿足:(minElement,maxElement] * 數學表示式為:minElement < x <= maxElement * */ public class ContinuousList { private double minElement; private double maxElement; public ContinuousList(double minElement,double maxElement){ if(minElement > maxElement){ throw new IllegalArgumentException("區間不合理,minElement不能大於maxElement!"); } this.minElement = minElement; this.maxElement = maxElement; } /** * 判斷當前集合是否包含特定元素 * @param element * @return */ public boolean isContainKey(double element){ boolean flag = false; if(element > minElement && element <= maxElement){ flag = true; } return flag; } } private List<ContinuousList> lotteryList; //概率連續集合 private double maxElement; //這裡只需要最大值,最小值預設為0.0 /** * 構造抽獎集合 * @param list 為獎品的概率 */ public LotteryUtil(List<Double> list){ lotteryList = new ArrayList<ContinuousList>(); if(list.size() == 0){ throw new IllegalArgumentException("抽獎集合不能為空!"); } double minElement = 0d; ContinuousList continuousList = null; for(Double d : list){ minElement = maxElement; maxElement = maxElement + d; continuousList = new ContinuousList(minElement,maxElement); lotteryList.add(continuousList); } } /** * 進行抽獎操作 * 返回:獎品的概率list集合中的下標 */ public int randomColunmIndex(){ int index = -1; Random r = new Random(); double d = r.nextDouble() * maxElement; //生成0-1間的隨機數 if(d == 0d){ d = r.nextDouble() * maxElement; //防止生成0.0 } int size = lotteryList.size(); for(int i = 0; i < size; i++){ ContinuousList cl = lotteryList.get(i); if(cl.isContainKey(d)){ index = i; break; } } if(index == -1){ throw new IllegalArgumentException("概率集合設定不合理!"); } return index; } public double getMaxElement() { return maxElement; } public List<ContinuousList> getLotteryList() { return lotteryList; } public void setLotteryList(List<ContinuousList> lotteryList) { this.lotteryList = lotteryList; } }
該工具類的基本思想是,將抽獎概率分佈到數軸上,如現有三個抽獎概率10、20、30,將三者依次新增到概率集合中,則構造的數軸為:0~10範圍內表示概率10,10~30範圍內表示概率為20,30~60範圍內表示概率為30,數軸上的長度對應著相應的概率。由這種處理方式可知,概率總和並不需要等於1。該工具類的成功與否在於Random.nextDouble()能否等概率地生成0~1之間的任意一個數。
對該抽獎工具進行測試,測試類如下:
package com.lottery; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; class Result{ private int index; private int sumTime; private int time; private double probability; private double realProbability; public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public int getTime() { return time; } public void setTime(int time) { this.time = time; } public int getSumTime() { return sumTime; } public void setSumTime(int sumTime) { this.sumTime = sumTime; } public double getProbability() { return probability; } public double getRealProbability() { return realProbability; } public void setRealProbability(double realProbability) { this.realProbability = realProbability; } public Result(){ } public Result(int index,int sumTime,int time,double realProbability) { this.setIndex(index); this.setTime(time); this.setSumTime(sumTime); this.setRealProbability(realProbability); } public String toString(){ return "索引值:" + index + ",抽獎總數:" + sumTime + ",抽中次數:" + time + ",概率:" + realProbability + ",實際概率:" + (double)time/sumTime; } } public class TestLottery { static final int TIME = 100000; public static void iteratorMap(Map<Integer,Integer> map,List<Double> list){ for(Entry<Integer,Integer> entry : map.entrySet()){ int index = entry.getKey(); int time = entry.getValue(); Result result = new Result(index,TIME,time,list.get(index)); System.out.println(result); } } public static void main(String[] args) { //構造概率集合 List<Double> list = new ArrayList<Double>(); list.add(20d); list.add(80d); list.add(50d); list.add(30d); LotteryUtil ll = new LotteryUtil(list); double sumProbability = ll.getMaxElement(); Map<Integer,Integer> map = new HashMap<Integer,Integer>(); for(int i = 0; i < TIME; i++){ int index = ll.randomColunmIndex(); if(map.containsKey(index)){ map.put(index,map.get(index) + 1); }else{ map.put(index,1); } } for(int i = 0; i < list.size(); i++){ double probability = list.get(i) / sumProbability; list.set(i,probability); } iteratorMap(map,list); } }
執行結果:
由結果可知,抽獎100000時, 得到的實際概率基本與正式概率相當。
以下說明此類呼叫方式:
public LotteryUtil(List<Double> list)
說明:構造方法,傳入引數為一個概率集合
public int randomColunmIndex()
功能:進行抽獎操作,返回List集合的索引下標,此下標對應的概率的獎品即為抽中的獎品
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。