java红包算法_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 = (max1pareTo(max2) < 0) ? max1 : max2;
BigDecimal amount = random.multiply(max).setScale(scale, BigDecimal.ROUND_DOWN);
//每个红包的数额不能⼩于预设的最⼩⾦额
if (amountpareTo(minAmount) < 0) {
amount = minAmount;
}
remainAmount = remainAmount.subtract(amount).setScale(scale, BigDecimal.ROUND_DOWN);
remainSize = remainSize - 1;
}
//最后⼀个红包,⾦额等于剩余⾦额
BigDecimal amount = remainAmount;
}
最后,未领取的⾦额需要退回给发红包的⽤户。写⼀个定时任务,将未领取的⼦红包退回即可。
如果在⽤户每次领取红包的时候⽣成⼀个⼦红包,算法也是⼀样的,只是每领取⼀次⼦红包后,都要更新总红包的余额和剩余数量,然后在退回过期红包时,将总红包的余额退回给发红包的⽤户即可。bigdecimal转换为integer

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。