JAVA实现拼手气红包算法
实现拼手气红包算法,有以下几个需要注意的地方:
- 抢红包的期望收益应与先后顺序无关
- 保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如区块链货币或者积分,需要自定义一个最小金额。
- 所有抢红包的人领取的子红包的金额之和加起来,等于发红包的人发出的总红包的金额。
下面实现的方式是一次生成所有的子红包,让用户按顺序领取。也可以每领取一个生成一个,两种方式性能上各有优劣。
代码如下:
/**
* 拼手气红包算法
* @param totalAmount 红包总金额
* @param size 领取人数
* @param scale 红包金额需要保留的小数位数
* @param minAmount 单个红包的最小金额
*/
private void randomHandOutAlgorithm(BigDecimal totalAmount, Integer size
, Integer scale, BigDecimal minAmount) {
//剩余红包金额
BigDecimal remainAmount = totalAmount.setScale(scale, BigDecimal.ROUND_DOWN);
//剩余红包个数
Integer remainSize = size;
for (int i = 1; i < size; i++) {
//前n-1个红包的金额,用随机算法
BigDecimal random = BigDecimal.valueOf(Math.random());
BigDecimal halfRemainSize = BigDecimal.valueOf(remainSize).divide(new BigDecimal(2), BigDecimal.ROUND_UP);
//计算单次红包的最大值,该算法也是微信的红包算法,可以保证抢红包的期望收益应与先后顺序无关,但后抢红包的方差更大,因此手气最佳更可能在后抢的人中诞生
BigDecimal max1 = remainAmount.divide(halfRemainSize, BigDecimal.ROUND_DOWN);
//同时,最大值需要保证,减去该红包后,剩下的红包足以满足剩余人数的最小金额
BigDecimal minRemainAmount = minAmount.multiply(BigDecimal.valueOf(remainSize - 1)).setScale(scale, BigDecimal.ROUND_DOWN);
BigDecimal max2 = remainAmount.subtract(minRemainAmount);
//最终,单次红包的最大值等于两个最大值中较小的一个
BigDecimal max = (max1.compareTo(max2) < 0) ? max1 : max2;
BigDecimal amount = random.multiply(max).setScale(scale, BigDecimal.ROUND_DOWN);
//每个红包的数额不能小于预设的最小金额
if (amount.compareTo(minAmount) < 0) {
amount = minAmount;
}
remainAmount = remainAmount.subtract(amount).setScale(scale, BigDecimal.ROUND_DOWN);
remainSize = remainSize - 1;
}
//最后一个红包,金额等于剩余金额
BigDecimal amount = remainAmount;
}
最后,未领取的金额需要退回给发红包的用户。写一个定时任务,将未领取的子红包退回即可。
如果在用户每次领取红包的时候生成一个子红包,算法也是一样的,只是每领取一次子红包后,都要更新总红包的余额和剩余数量,然后在退回过期红包时,将总红包的余额退回给发红包的用户即可。
JAVA实现拼手气红包算法的更多相关文章
- php实现微信拼手气红包
$result = sendHB(3, 5); echo '<pre>'; var_export($result); echo array_sum($result); /** * 拼手气红 ...
- java 实现仿照微信抢红包算法,实测结果基本和微信吻合,附demo
实现拼手气红包算法,有以下几个需要注意的地方: 抢红包的期望收益应与先后顺序无关 保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果需要发其他货币类型的红包,比如 ...
- 微信红包算法TEST
1.基本算法 设定总金额为10元,有N个人随机领取:N=1 则红包金额=X元: N=2 为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数 第二个红包=10-第一个红包金 ...
- Java判断回文数算法简单实现
好久没写java的代码了, 今天闲来无事写段java的代码,算是为新的一年磨磨刀,开个头,算法是Java判断回文数算法简单实现,基本思想是利用字符串对应位置比较,如果所有可能位置都满足要求,则输入的是 ...
- Java中常用的查找算法——顺序查找和二分查找
Java中常用的查找算法——顺序查找和二分查找 神话丿小王子的博客 一.顺序查找: a) 原理:顺序查找就是按顺序从头到尾依次往下查找,找到数据,则提前结束查找,找不到便一直查找下去,直到数据最后一位 ...
- 深入理解java虚拟机【垃圾回收算法】
Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...
- Java学习之二分查找算法
好久没写算法了.只记得递归方法..结果测试下爆栈了. 思路就是取范围的中间点,判断是不是要找的值,是就输出,不是就与范围的两个临界值比较大小,不断更新临界值直到找到为止,给定的集合一定是有序的. 自己 ...
- 如何用70行Java代码实现深度神经网络算法
http://www.tuicool.com/articles/MfYjQfV 如何用70行Java代码实现深度神经网络算法 时间 2016-02-18 10:46:17 ITeye 原文 htt ...
- Java面试常考------------------------垃圾收集算法
对于Java系学生而言,Java虚拟机中的垃圾收集算法是一个很重要的面试考点. 常用的垃圾收集算法主要可划分为以下三类: 1. 标记-清除算法 标记清除算法是一种比较简单的方法,直接标记内存中待回收的 ...
随机推荐
- java文件上传、下载、图片预览
多文件保存到本地: @ResponseBody @RequestMapping(value = "/uploadApp",produces = { "applica ...
- 泛微ecology OA系统在数据库配置信息泄露
漏洞描述 攻击者可通过该漏洞页面直接获取到数据库配置信息,攻击者可通过访问存在漏洞的页面并解密从而获取数据库配置信息,如攻击者可直接访问数据库,则可直接获取用户数据,由于泛微e-cology默认数据库 ...
- iview使用之怎样通过render函数在tabs组件中添加标签
在实际项目开发中我们通常会遇到一些比较'新颖'的需求,而这时iview库里往往没有现成可用的组件示例,所以我们就需要自己动手翻阅IviewAPI进行自定义一些组件,也可以说是将iview库里的多种组件 ...
- IDE使用GIT控制项目版本
IDEA本身继承GIT开发插件.只需要安装windows git客户端即可使用. check in project 检入项目 将新创建的项目上传到服务器. 对于git来说,空的目录不会上传到远程仓库. ...
- ip的运用
1------获取ip$ip=$_SERVICE['REMOTE_ADDR'];2------根据ip获取主机名gethostbyaddr($ip);3------根据主机名获取IPgethostby ...
- NC使用练习之通达OA-2017版本漏洞复现后续
利用上一篇通达OA的漏洞环境,练习NC工具的使用. 步骤: 1.本机启动nc.exe监听端口: 确认端口是否成功监听成功: 2.用冰蝎将nc.exe上传至目标机: 3.用命令行在目标机启动nc.exe ...
- java中有界队列的饱和策略(reject policy)
文章目录 AbortPolicy DiscardPolicy DiscardOldestPolicy CallerRunsPolicy 使用Semaphore java中有界队列的饱和策略(rejec ...
- Spring Boot Starters介绍
文章目录 Web Start Test Starter Data JPA Starter Mail Starter 结论 对于任何一个复杂项目来说,依赖关系都是一个非常需要注意和消息的方面,虽然重要, ...
- eclipse 创建maven项目失败
问题描述: eclipse 初次创建maven项目报错 可能是maven-archetype-quickstart:1.1.jar 包失效了或者没有? 有人说把这个jar包放在maven本地仓库里 我 ...
- Linux发送邮件命令mail,mutt
邮件常常是Linux下监控报警手段之一.Linux下的mail命令可以方便,快速的完成发送邮件. 1. Linux发邮件2种常见客户端命令 1.1 mail命令(推荐) 语法: 无邮件正文 mail ...