java 抽奖_java抽奖工具类:按概率抽奖
在一些抽奖活动中,会有按概率抽取奖品的操作,本文将提供一个抽奖概率的解决方案。
假设抽奖集合如下:
奖品id
概率
1
10%
2
10%
3
20%
4
20%
生成集合 生成的连续集合为{(0.0, 10.0],(10.0, 30.0],(30.0, 60.0]},如下:
奖品id
区间
1
(0.0, 10.0]
2
(10.0, 20.0]
3
(20.0, 40.0]
4
(40.0, 60.0]
最大的概率值 maxElement = 60.0,这个值下面会用到。
生成随机数
生成方法为 random.nextDouble() * maxElement,maxElement 就是上一步得到的。
判断随机数在哪个区间内,返回该区间对应的奖品id
假如 生成了随机数12.001,则它属于(10.0, 20.0],对应的奖品id为2.
代码如下:
LotteryUtil
public class LotteryUtil {
private List lotteryList;
private double maxElement;
/**
* 得到一个抽奖对象
* @param map 抽奖概率,key:奖品id,value:概率
* @param
* @return
*/
public static LotteryUtil getInstance(Map map) {
return new LotteryUtil(map);
}
/**
* 构造抽奖集合
* @param map 为奖品的概率
*/
private LotteryUtil(Map map) {
if(map.size() == 0){
throw new IllegalArgumentException("集合不能为空!");
}
double minElement = 0d;
lotteryList = new ArrayList<>(map.size());
for(Map.Entry entry : map.entrySet()) {
if(null == entry.getValue() || entry.getValue() <= 0) {
continue;
}
minElement = maxElement;
maxElement = maxElement + entry.getValue();
Continuous continuous = new Continuous(entry.getKey(), minElement, maxElement);
lotteryList.add(continuous);
}
}
/**
* 抽奖操作
*
* @return
*/
public T lottery() {
Random r = new Random();
//生成随机数
double d = r.nextDouble() * maxElement;
if(d == 0d) {
// 如果生成了0,就再生成一次
d = r.nextDouble() * maxElement;
}
int size = lotteryList.size();
for(int i = 0; i < size; i++){
Continuous continuous = lotteryList.get(i);
if(continuous.isContainKey(d)){
return (T)continuous.getVal();
}
}
return null;
}
/**
* 定义一个连续区间
* 集合中元素x满足:(minElement, maxElement]
* 数学表达式为:minElement < x <= maxElement
*
*/
class Continuous {
private Object val;
private double minElement;
private double maxElement;
public Continuous(Object val, double minElement, double maxElement) {
this.val = val;
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;
}
public Object getVal() {
return val;
}
public void setVal(Object val) {
this.val = val;
}
public double getMinElement() {
return minElement;
}
public void setMinElement(double minElement) {
this.minElement = minElement;
}
public double getMaxElement() {
return maxElement;
}
public void setMaxElement(double maxElement) {
this.maxElement = maxElement;
}
}
}
测试类:
LotteryUtilTest
public class LotteryUtilTest {
@Test
public void testLottery() {
Map map = new HashMap<>();
map.put(1, 0.10d);
map.put(2, 0.10d);
map.put(3, 0.20d);
map.put(4, 0.20d);
Map retMap = new HashMap<>();
int times = 100000;
LotteryUtil lotteryUtil = LotteryUtil.getInstance(map);
for(int i = 0; i < times; i++) {
Integer result = lotteryUtil.lottery();
Integer num = retMap.get(result);
retMap.put(result, null == num ? 1 : num + 1);
}
System.out.println(retMap);
Map setRate = new HashMap<>();
double total = 0d;
for(Map.Entry entry : map.entrySet()) {
total += entry.getValue();
}
for(Map.Entry entry : map.entrySet()) {
setRate.put(entry.getKey(), entry.getValue() / total);
}
Map realRate = new HashMap<>();
for(Map.Entry entry : retMap.entrySet()) {
realRate.put(entry.getKey(), (double)(entry.getValue()) / times);
}
for(Map.Entry entry : realRate.entrySet()) {
Integer key = entry.getKey();
System.out.println(String.format("奖品id为:%s, 抽奖次数为:%s, 设定的概率为:%s,实际的概率为:%s",
key, times, setRate.get(key), realRate.get(key)));
}
}
}
运行结果:
{1=16611, 2=16565, 3=33412, 4=33412}
奖品id为:1, 抽奖次数为:100000, 设定的概率为:0.16666666666666666,实际的概率为:0.16611
奖品id为:2, 抽奖次数为:100000, 设定的概率为:0.16666666666666666,实际的概率为:0.16565
奖品id为:3, 抽奖次数为:100000, 设定的概率为:0.3333333333333333,实际的概率为:0.33412
奖品id为:4, 抽奖次数为:100000, 设定的概率为:0.3333333333333333,实际的概率为:0.33412
java 抽奖_java抽奖工具类:按概率抽奖相关推荐
- java闭锁_Java并发工具类(闭锁CountDownLatch)
闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态. CountDownLatch是一种灵活的闭锁实现,它可以使一个或者多个线程等待一组事件的发生. 闭锁状态包含一个计数器,该计数器被初始化为 ...
- java 栅栏_Java 并发工具类(栅栏 CyclicBarrier )
CyclicBarrier适用于这样的情况:你希望创建一组任务,它们并行地执行工作,然后在下一个步骤之前等待,直到所有任务都完成.栅栏和闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. ...
- java 代理ip工具类_Java基础之java处理ip的工具类
java处理ip的工具类,包括把long类型的Ip转为一般Ip类型.把xx.xx.xx.xx类型的转为long类型.根据掩码位获取掩码.根据 ip/掩码位 计算IP段的起始IP.根据 ip/掩码位 计 ...
- java堆排序工具包_JAVA 排序工具类
提供了以下排序:冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 桶排序 堆排序 package com.xingej.algorithm.sort;import java.util.Arr ...
- java图片缩放工具类,一个JAVA图形缩放处置工具类
一个JAVA图形缩放处理工具类 调用的例子 import java.io.FileOutputStream; import java.io.IOException; import javax.imag ...
- JAVA I/O流工具类TextFile
JAVA I/O流工具类TextFile由广州疯狂软件java培训分享: 本文是一个TextFile类,通过这个类我们可以调用其中的方法来简化对文件的读写,这段代码的可用性比较强.这个TextFile ...
- java redis remove_最全的Java操作Redis的工具类
RedisUtil 当前版本:1.1 增加更全的方法,对以前的部分方法进行了规范命名,请放心替换成新版本. 介绍 最全的Java操作Redis的工具类,使用StringRedisTemplate实现, ...
- java图形验证码生成工具类
转载自 java图形验证码生成工具类 生成验证码效果 ValidateCode.java 验证码生成类 package cn.dsna.util.images; import java ...
- java练习(数组工具类的封装)[目前写过最长的代码,虽然不难]
java练习(数组工具类的封装)[目前写过最长的代码,虽然不难] package myUtil.arrayUtil;public class ArraysUtil {/*** 升序排列一个byte数组 ...
- java工具类应该抛异常吗,java学习阶段一 工具类(异常)
java学习阶段一 工具类(异常) 介绍 异常:运行期间出现的错误 背离程序本身意图的表现 基本知识 异常的分类 根类 Throwable Error 程序无法处理的错误 表示运行应用程序中教严重的问 ...
最新文章
- DELL 向左走 向右走?(二)
- 汇编语言——可由指令直接指定的I/O端口数
- 基于 VS 2010 阐述C# 4个特性
- abp执行mysql语句_在ABP模板工程中使用MySql
- python3 字典合并_python3字典合并怎么做?
- 毕业设计(五)---spring学习笔记(3)之-dataSource,sessionFactory,hibernateTemplate,事务 的简单配置。...
- Floyd算法 C++实现
- JavaSE基础———Set接口中的常用类HashSet、LinkedHashSet和TreeSet
- 一个都不能少:全面认识IE插件
- java中使用activiti(工作流)
- ltp测试操作步详解(压力测试网站最详、下载、使用)
- 新浪微博热门话题(30 分)(字符串)
- [XJTU计算机网络安全与管理]——第八讲密钥管理和分发
- 转载:python中的pygame编写飞机大战(七) 播放爆炸动画
- Android 监听wifi热点打开和关闭广播
- matlab抠图数据,MATLAB抠图
- 靓仔的个人邮箱推荐——靓号邮箱!
- 在c语言中 auto的作用,c语言中auto是什么意思
- 十句冥思話--人生感悟
- ubuntu 限速 流量监控工具 - iftop
热门文章
- Unity 搭建ILRuntime开发环境
- Python爬取bilibili视频(期末设计)
- 地震发生时的避险与逃生
- 如何使用C#复制或移动Excel工作表?试试Aspose
- 美国谍梦第一季/全集The Americans迅雷下载
- Continuum robot(Concentric tube robotConstant curvature robot)分析笔记
- 计算机信息的编码教案,信息编码教案
- aide可以用mysql吗,aide使用手册
- CATIA CAA二次开发视频教程 CAA资料
- 上传插件推荐:WebUploader是一款非常强大的前端上传插件