java實(shí)現(xiàn)抽獎(jiǎng)概率類(lèi)
本文實(shí)例為大家分享了java實(shí)現(xiàn)抽獎(jiǎng)概率類(lèi)的具體代碼,供大家參考,具體內(nèi)容如下
在一些項(xiàng)目需求中,可能會(huì)遇到抽獎(jiǎng)問(wèn)題,如提供一系列獎(jiǎng)品及獲獎(jiǎng)概率,要求根據(jù)概率返回每次抽到的獎(jiǎng)品。以下是本人在實(shí)際項(xiàng)目中寫(xiě)的一個(gè)抽獎(jiǎng)工具類(lèi),與大家共同分享:
import java.util.ArrayList;import java.util.List;import java.util.Random; /** * 抽獎(jiǎng)工具類(lèi),概率和可以不等于1 * 概率為百分?jǐn)?shù)去掉百分號(hào)的部分,如10%,則為10 * 抽獎(jiǎng)操作如下: * 1.輸入抽獎(jiǎng)概率集合,【抽獎(jiǎng)概率集合為{10.0, 20.0, 30.0}】 * 2.生成連續(xù)集合, 【生成的連續(xù)集合為{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]}】 * 3.生成隨機(jī)數(shù), 【生成方法為 random.nextDouble() * maxElement】 * 4.判斷隨機(jī)數(shù)在哪個(gè)區(qū)間內(nèi),返回該區(qū)間的index【生成了隨機(jī)數(shù)12.001,則它屬于(10.0, 30.0],返回 index = 1】 * */public class LotteryUtil { /** * 定義一個(gè)連續(xù)集合 * 集合中元素x滿足:(minElement,maxElement] * 數(shù)學(xué)表達(dá)式為:minElement < x <= maxElement * */ public class ContinuousList { private double minElement; private double maxElement; public ContinuousList(double minElement, double maxElement){ if(minElement > maxElement){ throw new IllegalArgumentException('區(qū)間不合理,minElement不能大于maxElement!'); } this.minElement = minElement; this.maxElement = maxElement; } /** * 判斷當(dāng)前集合是否包含特定元素 * @param element * @return */ public boolean isContainKey(double element){ boolean flag = false; if(element > minElement && element <= maxElement){ flag = true; } return flag; } } private List<ContinuousList> lotteryList; //概率連續(xù)集合 private double maxElement; //這里只需要最大值,最小值默認(rèn)為0.0 /** * 構(gòu)造抽獎(jiǎng)集合 * @param list 為獎(jiǎng)品的概率 */ public LotteryUtil(List<Double> list){ lotteryList = new ArrayList<ContinuousList>(); if(list.size() == 0){ throw new IllegalArgumentException('抽獎(jiǎng)集合不能為空!'); } double minElement = 0d; ContinuousList continuousList = null; for(Double d : list){ minElement = maxElement; maxElement = maxElement + d; continuousList = new ContinuousList(minElement, maxElement); lotteryList.add(continuousList); } } /** * 進(jìn)行抽獎(jiǎng)操作 * 返回:獎(jiǎng)品的概率list集合中的下標(biāo) */ public int randomColunmIndex(){ int index = -1; Random r = new Random(); double d = r.nextDouble() * maxElement; //生成0-1間的隨機(jī)數(shù) 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('概率集合設(shè)置不合理!'); } return index; } public double getMaxElement() { return maxElement; } public List<ContinuousList> getLotteryList() { return lotteryList; } public void setLotteryList(List<ContinuousList> lotteryList) { this.lotteryList = lotteryList; } }
該工具類(lèi)的基本思想是,將抽獎(jiǎng)概率分布到數(shù)軸上,如現(xiàn)有三個(gè)抽獎(jiǎng)概率10、20、30,將三者依次添加到概率集合中,則構(gòu)造的數(shù)軸為:0~10范圍內(nèi)表示概率10,10~30范圍內(nèi)表示概率為20,30~60范圍內(nèi)表示概率為30,數(shù)軸上的長(zhǎng)度對(duì)應(yīng)著相應(yīng)的概率。由這種處理方式可知,概率總和并不需要等于1。該工具類(lèi)的成功與否在于Random.nextDouble()能否等概率地生成0~1之間的任意一個(gè)數(shù)。
對(duì)該抽獎(jiǎng)工具進(jìn)行測(cè)試,測(cè)試類(lèi)如下:
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 + ',抽獎(jiǎng)總數(shù):' + sumTime + ',抽中次數(shù):' + time + ',概率:' + realProbability + ',實(shí)際概率:' + (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) { //構(gòu)造概率集合 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); }}
運(yùn)行結(jié)果:
由結(jié)果可知,抽獎(jiǎng)100000時(shí), 得到的實(shí)際概率基本與正式概率相當(dāng)。
以下說(shuō)明此類(lèi)調(diào)用方式:
public LotteryUtil(List<Double> list)說(shuō)明:構(gòu)造方法,傳入?yún)?shù)為一個(gè)概率集合
public int randomColunmIndex()功能:進(jìn)行抽獎(jiǎng)操作,返回List集合的索引下標(biāo),此下標(biāo)對(duì)應(yīng)的概率的獎(jiǎng)品即為抽中的獎(jiǎng)品
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問(wèn)題及解決2. python爬蟲(chóng)實(shí)戰(zhàn)之制作屬于自己的一個(gè)IP代理模塊3. 如何在jsp界面中插入圖片4. HTML 絕對(duì)路徑與相對(duì)路徑概念詳細(xì)5. WML的簡(jiǎn)單例子及編輯、測(cè)試方法第1/2頁(yè)6. 詳解盒子端CSS動(dòng)畫(huà)性能提升7. 解決ajax請(qǐng)求后臺(tái),有時(shí)收不到返回值的問(wèn)題8. asp批量添加修改刪除操作示例代碼9. .NET6打包部署到Windows Service的全過(guò)程10. ajax請(qǐng)求后臺(tái)得到j(luò)son數(shù)據(jù)后動(dòng)態(tài)生成樹(shù)形下拉框的方法
