java實現(xiàn)抽獎概率類
本文實例為大家分享了java實現(xiàn)抽獎概率類的具體代碼,供大家參考,具體內(nèi)容如下
在一些項目需求中,可能會遇到抽獎問題,如提供一系列獎品及獲獎概率,要求根據(jù)概率返回每次抽到的獎品。以下是本人在實際項目中寫的一個抽獎工具類,與大家共同分享:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 抽獎工具類,概率和可以不等于1
* 概率為百分?jǐn)?shù)去掉百分號的部分,如10%,則為10
* 抽獎操作如下:
* 1.輸入抽獎概率集合,【抽獎概率集合為{10.0, 20.0, 30.0}】
* 2.生成連續(xù)集合, 【生成的連續(xù)集合為{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]}】
* 3.生成隨機數(shù), 【生成方法為 random.nextDouble() * maxElement】
* 4.判斷隨機數(shù)在哪個區(qū)間內(nèi),返回該區(qū)間的index【生成了隨機數(shù)12.001,則它屬于(10.0, 30.0],返回 index = 1】
*
*/
public class LotteryUtil {
/**
* 定義一個連續(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)造抽獎集合
* @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);
}
}
/**
* 進(jìn)行抽獎操作
* 返回:獎品的概率list集合中的下標(biāo)
*/
public int randomColunmIndex(){
int index = -1;
Random r = new Random();
double d = r.nextDouble() * maxElement; //生成0-1間的隨機數(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;
}
}
該工具類的基本思想是,將抽獎概率分布到數(shù)軸上,如現(xiàn)有三個抽獎概率10、20、30,將三者依次添加到概率集合中,則構(gòu)造的數(shù)軸為:0~10范圍內(nèi)表示概率10,10~30范圍內(nèi)表示概率為20,30~60范圍內(nèi)表示概率為30,數(shù)軸上的長度對應(yīng)著相應(yīng)的概率。由這種處理方式可知,概率總和并不需要等于1。該工具類的成功與否在于Random.nextDouble()能否等概率地生成0~1之間的任意一個數(shù)。
對該抽獎工具進(jìn)行測試,測試類如下:
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 + ",抽獎總數(shù):" + sumTime + ",抽中次數(shù):" + 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) {
//構(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);
}
}
運行結(jié)果:

由結(jié)果可知,抽獎100000時, 得到的實際概率基本與正式概率相當(dāng)。
以下說明此類調(diào)用方式:
public LotteryUtil(List<Double> list)
說明:構(gòu)造方法,傳入?yún)?shù)為一個概率集合
public int randomColunmIndex()
功能:進(jìn)行抽獎操作,返回List集合的索引下標(biāo),此下標(biāo)對應(yīng)的概率的獎品即為抽中的獎品
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring@Autowired與@Resource的區(qū)別有哪些
這篇文章主要為大家詳細(xì)介紹了@Autowired與@Resource的區(qū)別,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02
SpringCloud之熔斷器Hystrix的實現(xiàn)
這篇文章主要介紹了SpringCloud之熔斷器Hystrix的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
pom.xml中解決Provides?transitive?vulnerable?dependency?mave
這篇文章主要介紹了在pom.xml中如何解決Provides?transitive?vulnerable?dependency?maven:org.yaml:snakeyaml:1.33警告問題,需要的朋友可以參考下2023-06-06
java多次嵌套循環(huán)查詢數(shù)據(jù)庫導(dǎo)致代碼中數(shù)據(jù)處理慢的解決
這篇文章主要介紹了java多次嵌套循環(huán)查詢數(shù)據(jù)庫導(dǎo)致代碼中數(shù)據(jù)處理慢的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

