java使用BigDecimal 实现随机金额红包拆分算法
原创代码,引用注明出处:https://www.cnblogs.com/guangxiang/p/12218714.html @Service
public class SplitRedPacketsServiceImpl implements SplitRedPacketsService {
//红包最大金额
private static final BigDecimal MAXMONEY = new BigDecimal("200"); /**
* 红包拆分生成list集合
* 1.生成count个红包的list,将最小金额分配到每个红包上
* 2.随机生成一个数值,在原list上做加法
* @param money 总金额
* @param count 总数
* @param minmoney 最小金额
* @param maxmoney 最大金额
* @param bigred 大包固定金额
* @param bigcount 大包个数
* @return
*/
public List<BigDecimal> splitRedPackets(BigDecimal money, BigDecimal maxmoney, BigDecimal minmoney, BigDecimal count, BigDecimal bigred, BigDecimal bigcount)
{
//计算小包金额总数和总金额
count = count.subtract(bigcount);
money = money.subtract(bigcount.multiply(bigred)); //大包固定金额集合
List<BigDecimal> bigList = new ArrayList<BigDecimal>();
for(int i=0;i<bigcount.intValue();i++)
{
bigList.add(bigred);
} //原始list--小包list
List<BigDecimal> list = new ArrayList<BigDecimal>();
maxmoney = (maxmoney.compareTo(MAXMONEY)==1)?MAXMONEY:maxmoney; /**
* 1.将最小金额分配到每个红包上
* 2.减去分配的小包金额
* 3.剩余总金额 =总金额-最小金额*最小金额数
*/
for(int i=0;i<count.intValue();i++)
{
list.add(minmoney);
}
BigDecimal minsum = minmoney.multiply(count);
BigDecimal totalMoney = money.subtract(minsum);
BigDecimal realMaxmoney = maxmoney.subtract(minmoney); //判断是否符合取值区间
if(!isRight(totalMoney,count,realMaxmoney,new BigDecimal("0")))
{
return null;
} //合并后的新包
List<BigDecimal> listnew = new ArrayList<BigDecimal>();
for(int i=0;i<list.size();i++)
{
BigDecimal one = randomRedPacket(totalMoney,new BigDecimal("0"),realMaxmoney,new BigDecimal(count.intValue()-i));
listnew.add(list.get(i).add(one));
totalMoney = totalMoney.subtract(one);
} //合并打包固定金额集合
listnew.addAll(bigList);
Collections.shuffle(listnew);
return listnew;
} /**
* 随机方法产生一个在最大值和最小值之间的一个红包,
* 并判断该红包是否合法,是否在产生这个红包之后红包金额变成负数。
* 另外,在这次产生红包值较小时,下一次就产生一个大一点的红包。
* @param money 总金额
* @param mins 最小金额
* @param maxs 最大金额
* @param count 红包总数
* @return
*/
private BigDecimal randomRedPacket(BigDecimal money,BigDecimal mins,BigDecimal maxs,BigDecimal count)
{
if(count.intValue()==1)
{
return money.setScale(2,BigDecimal.ROUND_UP);
}
if(mins.compareTo(maxs)==0 )
{
return mins;//如果最大值和最小值一样,就返回mins
}
BigDecimal max = (maxs.compareTo(money)==1)?money:maxs;
//返回指定范围的随机数,保留两位小数
BigDecimal random = BigDecimal.valueOf(Math.random());
BigDecimal middle = maxs.subtract(mins);
BigDecimal middle2 = random.multiply(middle).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal one = middle2.add(mins); BigDecimal moneyOther = money.subtract(one);
if(isRight(moneyOther,count.subtract(new BigDecimal("1")),maxs,mins))
{
return one;
}
else{
//重新分配
BigDecimal avg = moneyOther.divide(count.subtract(new BigDecimal("1")),2,BigDecimal.ROUND_UP);
if(avg.compareTo(mins)==-1)
{
return randomRedPacket(money,mins,one,count);
}else if(avg.compareTo(maxs)==1)
{
return randomRedPacket(money,one,maxs,count);
}
}
return one;
} /**
* 判断是否符合取值区间
* @param money 总金额
* @param count 总数
* @return
*/
private boolean isRight(BigDecimal money,BigDecimal count,BigDecimal maxs,BigDecimal mins)
{
BigDecimal avg = money.divide(count,2,BigDecimal.ROUND_UP);
if(avg.compareTo(mins) ==-1){
return false;
}
else if(avg.compareTo(maxs) ==1)
{
return false;
}
return true;
}
java使用BigDecimal 实现随机金额红包拆分算法的更多相关文章
- java实现微信红包分配算法
红包算法分析 有人认为,抢红包的额度是从0.01到剩余平均值*N(N是一个系数,决定最大的红包值)之间,比如一共发了10块钱,发了10个红包:第一个人可以拿到(0.01~1*N)之间的一个红包值,当然 ...
- .Net Excel 导出图表Demo(柱状图,多标签页) .net工具类 分享一个简单的随机分红包的实现方式
.Net Excel 导出图表Demo(柱状图,多标签页) 1 使用插件名称Epplus,多个Sheet页数据应用,Demo为柱状图(Epplus支持多种图表) 2 Epplus 的安装和引用 新建一 ...
- java.math.BigDecimal保留两位小数,保留小数,精确位数
http://blog.csdn.net/yuhua3272004/article/details/3075436 使用java.math.BigDecimal工具类实现 java保留两位小数问题 ...
- Java之BigDecimal详解
一.BigDecimal概述 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实 ...
- Java基础扫盲系列(二)—— Java中BigDecimal和浮点类型
一直以来我几乎未使用过BigDecimal类型,只有在DB中涉及到金额字段时听说要用Decimal类型,但是今天再项目代码中看到使用BigDecimal表示贷款金额. 本篇文章不是介绍BigDecim ...
- Java的BigDecimal,对运算封装
添加maven依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava ...
- flex布局中flex属性运用在随机发红包的算法上
flex布局是现在前端基本上都会运用的一种布局,基本上用到比较多的是父元素设置display:flex,两个子元素,一个设置固定宽度,另一个设置为flex:1(这里都指flex-direction为r ...
- java中BigDecimal加减乘除基本用法
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数. 在实际应用中,需要对更大或者更小的数进 ...
- Java中BigDecimal的8种舍入模式
java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成. 如果为零或正数,则标度是小数点后的位 ...
随机推荐
- P1090 危险品装箱
1090 危险品装箱 (25分) 集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里.比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸. 本题给定一张不相容物品的清单,需要你 ...
- Ubuntu下安装 Mysql
MYSQL在ubuntu16.04下的编译安装mysql-5.6.23.tar.gz 为减少安装过程中因权限带来个各种问题,建议全程用root用户编译安装,步骤如下: 1.安装依赖文件 apt-ge ...
- XV6源代码阅读-同步机制
Exercise1 源代码阅读 锁部分:spinlock.h/spinlock.c以及相关其他文件代码 // Mutual exclusion lock. struct spinlock { uint ...
- mysql 权限管理 grant revoke
grant all privileges on database.table to 'user'@'ip' identified by 'passwd' with grant option; g ...
- CLion的使用
配置远程Linux编译器 实现目标:1.将项目中的源码和target和Linux服务器同步.2.代码在服务器端运行 配置ToolChains setting -> Build,Execution ...
- Day6 - H - Balanced Lineup POJ - 3264
For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One d ...
- Go 函数与闭包
函数 1.函数与闭包 func adder() func (value int){ sum := 0 return func(value int) int{ sum += value return s ...
- String+、intern()、字符串常量池
字符串连接符 "+"及字符串常量池实验.字符串final属性 结果预览 public class StrTest{ public static void main(String[] ...
- 010.Oracle数据库 , ORDER BY 按升序降序排序
/*Oracle数据库查询日期在两者之间*/ SELECT DISTINCT ATA FROM LM_FAULT WHERE ( OCCUR_DATE BETWEEN to_date( '2017-0 ...
- 0101-ioc
背景 ioc是spring的基础,即控制反转.springboot基于注解使用ioc. ioc spring称所有被管理的对象为bean, spring ioc主要通过描述的方式完成3类bean的管理 ...