在一些抽奖活动中,会有按概率抽取奖品的操作,本文将提供一个抽奖概率的解决方案。

假设抽奖集合如下:

奖品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抽奖工具类:按概率抽奖相关推荐

  1. java闭锁_Java并发工具类(闭锁CountDownLatch)

    闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态. CountDownLatch是一种灵活的闭锁实现,它可以使一个或者多个线程等待一组事件的发生. 闭锁状态包含一个计数器,该计数器被初始化为 ...

  2. java 栅栏_Java 并发工具类(栅栏 CyclicBarrier )

    CyclicBarrier适用于这样的情况:你希望创建一组任务,它们并行地执行工作,然后在下一个步骤之前等待,直到所有任务都完成.栅栏和闭锁的关键区别在于,所有线程必须同时到达栅栏位置,才能继续执行. ...

  3. java 代理ip工具类_Java基础之java处理ip的工具类

    java处理ip的工具类,包括把long类型的Ip转为一般Ip类型.把xx.xx.xx.xx类型的转为long类型.根据掩码位获取掩码.根据 ip/掩码位 计算IP段的起始IP.根据 ip/掩码位 计 ...

  4. java堆排序工具包_JAVA 排序工具类

    提供了以下排序:冒泡排序 选择排序 插入排序 希尔排序 快速排序 归并排序 桶排序 堆排序 package com.xingej.algorithm.sort;import java.util.Arr ...

  5. java图片缩放工具类,一个JAVA图形缩放处置工具类

    一个JAVA图形缩放处理工具类 调用的例子 import java.io.FileOutputStream; import java.io.IOException; import javax.imag ...

  6. JAVA I/O流工具类TextFile

    JAVA I/O流工具类TextFile由广州疯狂软件java培训分享: 本文是一个TextFile类,通过这个类我们可以调用其中的方法来简化对文件的读写,这段代码的可用性比较强.这个TextFile ...

  7. java redis remove_最全的Java操作Redis的工具类

    RedisUtil 当前版本:1.1 增加更全的方法,对以前的部分方法进行了规范命名,请放心替换成新版本. 介绍 最全的Java操作Redis的工具类,使用StringRedisTemplate实现, ...

  8. java图形验证码生成工具类

    转载自   java图形验证码生成工具类 生成验证码效果       ValidateCode.java 验证码生成类 package cn.dsna.util.images; import java ...

  9. java练习(数组工具类的封装)[目前写过最长的代码,虽然不难]

    java练习(数组工具类的封装)[目前写过最长的代码,虽然不难] package myUtil.arrayUtil;public class ArraysUtil {/*** 升序排列一个byte数组 ...

  10. java工具类应该抛异常吗,java学习阶段一 工具类(异常)

    java学习阶段一 工具类(异常) 介绍 异常:运行期间出现的错误 背离程序本身意图的表现 基本知识 异常的分类 根类 Throwable Error 程序无法处理的错误 表示运行应用程序中教严重的问 ...

最新文章

  1. DELL 向左走 向右走?(二)
  2. 汇编语言——可由指令直接指定的I/O端口数
  3. 基于 VS 2010 阐述C# 4个特性
  4. abp执行mysql语句_在ABP模板工程中使用MySql
  5. python3 字典合并_python3字典合并怎么做?
  6. 毕业设计(五)---spring学习笔记(3)之-dataSource,sessionFactory,hibernateTemplate,事务 的简单配置。...
  7. Floyd算法 C++实现
  8. JavaSE基础———Set接口中的常用类HashSet、LinkedHashSet和TreeSet
  9. 一个都不能少:全面认识IE插件
  10. java中使用activiti(工作流)
  11. ltp测试操作步详解(压力测试网站最详、下载、使用)
  12. 新浪微博热门话题(30 分)(字符串)
  13. [XJTU计算机网络安全与管理]——第八讲密钥管理和分发
  14. 转载:python中的pygame编写飞机大战(七) 播放爆炸动画
  15. Android 监听wifi热点打开和关闭广播
  16. matlab抠图数据,MATLAB抠图
  17. 靓仔的个人邮箱推荐——靓号邮箱!
  18. 在c语言中 auto的作用,c语言中auto是什么意思
  19. 十句冥思話--人生感悟
  20. ubuntu 限速 流量监控工具 - iftop

热门文章

  1. Unity 搭建ILRuntime开发环境
  2. Python爬取bilibili视频(期末设计)
  3. 地震发生时的避险与逃生
  4. 如何使用C#复制或移动Excel工作表?试试Aspose
  5. 美国谍梦第一季/全集The Americans迅雷下载
  6. Continuum robot(Concentric tube robotConstant curvature robot)分析笔记
  7. 计算机信息的编码教案,信息编码教案
  8. aide可以用mysql吗,aide使用手册
  9. CATIA CAA二次开发视频教程 CAA资料
  10. 上传插件推荐:WebUploader是一款非常强大的前端上传插件