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. 标记-清除算法 标记清除算法是一种比较简单的方法,直接标记内存中待回收的 ...
随机推荐
- Python刷CSDN阅读数(仅供娱乐)
#!/usr/bin/env python # -*- coding: utf-8 -*- """ @File:csdn_reads.py @E-mail:3649427 ...
- IDEA惊天bug:进程已结束,退出代码-1073741819 (0xC0000005)
由于昨天要写的文章没有写完,于是今天早上我四点半就"自然醒"了,心里面有事,睡觉也不安稳.洗漱完毕后,我打开电脑,正襟危坐,摆出一副要干架的态势,不能再拖了. 要写的文章中涉及到一 ...
- Linux下jdk的安装和环境变量的配置
Linux下jdk的安装和环境变量的配置 一.jdk的下载 方式一:在官网下载 http://www.oracle.com/technetwork/java/javase/downloads/inde ...
- 2019-2020-1 20199326《Linux内核原理与分析》第六周作业
本周学习了庖丁解牛Linux内核分析第五章:系统调用的三层机制(下),是上一章的延续 实验内容:使用gdb跟踪分析一个系统调用内核函数 上周实验我选择的getpid这个系统系统调用,这次准备使用gdb ...
- I/O多路复用之select,poll,epoll简介
一.select 1.起源 select最早于1983年出现在4.2BSD中(BSD是早期的UNIX版本的分支). 它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回 ...
- Hawkeye部署Github监控系统
2019独角兽企业重金招聘Python工程师标准>>> step1:python环境安装 #pwd /usr/local/soft #wget https://www.python. ...
- (PSO-BP)结合粒子群的神经网络算法以及matlab实现
原理: PSO(粒子群群算法):可以在全局范围内进行大致搜索,得到一个初始解,以便BP接力 BP(神经网络):梯度搜素,细化能力强,可以进行更仔细的搜索.数据: ...
- BurpSuite 扩展开发[1]-API与HelloWold
园长 · 2014/11/20 15:08 0x00 简介 BurpSuite神器这些年非常的受大家欢迎,在国庆期间解了下Burp相关开发并写了这篇笔记.希望和大家分享一下JavaSwing和Burp ...
- 12c DG broker DMON自动重启过程分析
一.知识点 1.强烈建议大家管理dataguard使用broker. 2.broker的日志要知道在哪里,会看日志是学习的第一步. 3.体系结构需要看官方文档. 二.测试过程 1.查看DMON进程 & ...
- CSS3轻松实现彩色旋转六面体动画
一.效果预览: 二.基本思路: 1.首先这个一个自动触发的动画,因此应使用animation设计,包括自动组装和组装完成后自动旋转的过程: 2.当鼠标放上去的时候六个面及上面的字体均变色,应在六个面设 ...