java 随机金额_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 splitRedPackets(BigDecimal money, BigDecimal maxmoney, BigDecimal minmoney, BigDecimal count, BigDecimal bigred, BigDecimal bigcount)

{

//计算小包金额总数和总金额

count = count.subtract(bigcount);

money = money.subtract(bigcount.multiply(bigred));

//大包固定金额集合

List bigList = new ArrayList();

for(int i=0;i

{

bigList.add(bigred);

}

//原始list--小包list

List list = new ArrayList();

maxmoney = (maxmoney.compareTo(MAXMONEY)==1)?MAXMONEY:maxmoney;

/**

* 1.将最小金额分配到每个红包上

* 2.减去分配的小包金额

* 3.剩余总金额 =总金额-最小金额*最小金额数

*/

for(int i=0;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 listnew = new ArrayList();

for(int i=0;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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值