java 红包算法_JAVA实现拼手气红包算法
實現(xiàn)拼手氣紅包算法,有以下幾個需要注意的地方:
搶紅包的期望收益應與先后順序無關
保證每個用戶至少能搶到一個預設的最小金額,人民幣紅包設置的最小金額一般是0.01元,如果需要發(fā)其他貨幣類型的紅包,比如區(qū)塊鏈貨幣或者積分,需要自定義一個最小金額。
所有搶紅包的人領取的子紅包的金額之和加起來,等于發(fā)紅包的人發(fā)出的總紅包的金額。
下面實現(xiàn)的方式是一次生成所有的子紅包,讓用戶按順序領取。也可以每領取一個生成一個,兩種方式性能上各有優(yōu)劣。
代碼如下:
/**
* 拼手氣紅包算法
* @param totalAmount 紅包總金額
* @param size 領取人數(shù)
* @param scale 紅包金額需要保留的小數(shù)位數(shù)
* @param minAmount 單個紅包的最小金額
*/
private void randomHandOutAlgorithm(BigDecimal totalAmount, Integer size
, Integer scale, BigDecimal minAmount) {
//剩余紅包金額
BigDecimal remainAmount = totalAmount.setScale(scale, BigDecimal.ROUND_DOWN);
//剩余紅包個數(shù)
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);
//同時,最大值需要保證,減去該紅包后,剩下的紅包足以滿足剩余人數(shù)的最小金額
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);
//每個紅包的數(shù)額不能小于預設的最小金額
if (amount.compareTo(minAmount) < 0) {
amount = minAmount;
}
remainAmount = remainAmount.subtract(amount).setScale(scale, BigDecimal.ROUND_DOWN);
remainSize = remainSize - 1;
}
//最后一個紅包,金額等于剩余金額
BigDecimal amount = remainAmount;
}
最后,未領取的金額需要退回給發(fā)紅包的用戶。寫一個定時任務,將未領取的子紅包退回即可。
如果在用戶每次領取紅包的時候生成一個子紅包,算法也是一樣的,只是每領取一次子紅包后,都要更新總紅包的余額和剩余數(shù)量,然后在退回過期紅包時,將總紅包的余額退回給發(fā)紅包的用戶即可。
總結
以上是生活随笔為你收集整理的java 红包算法_JAVA实现拼手气红包算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 按钮防连点
- 下一篇: Java实用工具类-将汉字转为拼音