代码语言
.
CSharp
.
JS
Java
Asp.Net
C
MSSQL
PHP
Css
PLSQL
Python
Shell
EBS
ASP
Perl
ObjC
VB.Net
VBS
MYSQL
GO
Delphi
AS
DB2
Domino
Rails
ActionScript
Scala
代码分类
文件
系统
字符串
数据库
网络相关
图形/GUI
多媒体
算法
游戏
Jquery
Extjs
Android
HTML5
菜单
网页交互
WinForm
控件
企业应用
安全与加密
脚本/批处理
开放平台
其它
【
Java
】
实现一个抽奖概率类
作者:
/ 发布于
2017/1/13
/
428
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之间的任意一个数。 对该抽奖工具进行测试,测试类如下: [java] view plain copy 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); } } 以下说明此类调用方式: public LotteryUtil(List<Double> list) 说明:构造方法,传入参数为一个概率集合 view plain copy public int randomColunmIndex() 功能:进行抽奖操作,返回List集合的索引下标,此下标对应的概率的奖品即为抽中的奖品
试试其它关键字
同语言下
.
List 切割成几份 工具类
.
一行一行读取txt的内容
.
Java PDF转换成图片并输出给前台展示
.
java 多线程框架
.
double类型如果小数点后为零则显示整数否则保留两位小
.
将图片转换为Base64字符串公共类抽取
.
sqlParser 处理SQL(增删改查) 替换schema 用于多租户
.
JAVA 月份中的第几周处理 1-7属于第一周 依次类推 29-
.
java计算两个经纬度之间的距离
.
输入时间参数计算年龄
可能有用的
.
List 切割成几份 工具类
.
一行一行读取txt的内容
.
Java PDF转换成图片并输出给前台展示
.
java 多线程框架
.
double类型如果小数点后为零则显示整数否则保留两位小
.
将图片转换为Base64字符串公共类抽取
.
sqlParser 处理SQL(增删改查) 替换schema 用于多租户
.
JAVA 月份中的第几周处理 1-7属于第一周 依次类推 29-
.
java计算两个经纬度之间的距离
.
输入时间参数计算年龄
贡献的其它代码
Label
Copyright © 2004 - 2024 dezai.cn. All Rights Reserved
站长博客
粤ICP备13059550号-3