紅包分配算法,總金額分配算法

最近要做一個 總數和分配幾個點的數據, 但是又不能是平均值,所以寫一個隨機分配數,每個數的和加在一起等於總金額

類似於紅包分配方式,解釋說明都寫在類裏了

解釋和說明

* 1  搶紅包的期望收益應與先後順序無關
   2  保證每個用戶至少能搶到一個預設的最小金額,人民幣紅包設置的最小金額一般是0.01元,如果需要發其他貨幣類型的紅包,比如區塊鏈貨幣或者積分,需要自定義一個最小金額。
   3  所有搶紅包的人領取的子紅包的金額之和加起來,等於發紅包的人發出的總紅包的金額。 下面實現的方式是一次生成所有的子紅包,讓用戶按順序領取。也可以每領取一個生成一個,兩種方式性能上各有優劣。

 *  public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode)
    第一個參數是除數,第二個參數代表保留幾位小數,第三個代表的是使用的模式。其中我們標題上就是其中的兩種
    BigDecimal.ROUND_DOWN:直接省略多餘的小數,比如1.28如果保留1位小數,得到的就是1.2

    BigDecimal.ROUND_UP:直接進位,比如1.21如果保留1位小數,得到的就是1.3

    BigDecimal.ROUND_HALF_UP:四捨五入,2.35保留1位,變成2.4

    BigDecimal.ROUND_HALF_DOWN:四捨五入,2.35保留1位,變成2.3

總體紅包算法, 1 定義總金額和紅包個數 2 確定紅包的最大值和最小值
     3 在最大值裏隨機分配一個小數與之相乘,等到的是實際紅包金額
     4 再減去已經生成領取的紅包金額和個數。接着下一次再重新計算紅包;
     大致如下,
     max = moneytotal/count*2;
    實際紅包金額= max*Math.random();
    2.4=4*0.6 紅包大小取決於隨機大小(0.1~0.9)之間

 

 

import java.math.BigDecimal;

/*
 * 1  搶紅包的期望收益應與先後順序無關
   2  保證每個用戶至少能搶到一個預設的最小金額,人民幣紅包設置的最小金額一般是0.01元,如果需要發其他貨幣類型的紅包,比如區塊鏈貨幣或者積分,需要自定義一個最小金額。
   3  所有搶紅包的人領取的子紅包的金額之和加起來,等於發紅包的人發出的總紅包的金額。 下面實現的方式是一次生成所有的子紅包,讓用戶按順序領取。也可以每領取一個生成一個,兩種方式性能上各有優劣。

 *  public BigDecimal divide(BigDecimal divisor,int scale, int roundingMode)
    第一個參數是除數,第二個參數代表保留幾位小數,第三個代表的是使用的模式。其中我們標題上就是其中的兩種
    BigDecimal.ROUND_DOWN:直接省略多餘的小數,比如1.28如果保留1位小數,得到的就是1.2

    BigDecimal.ROUND_UP:直接進位,比如1.21如果保留1位小數,得到的就是1.3

    BigDecimal.ROUND_HALF_UP:四捨五入,2.35保留1位,變成2.4

    BigDecimal.ROUND_HALF_DOWN:四捨五入,2.35保留1位,變成2.3
————————————————
總體紅包算法, 1 定義總金額和紅包個數 2 確定紅包的最大值和最小值
     3 在最大值裏隨機分配一個小數與之相乘,等到的是實際紅包金額
     4 再減去已經生成領取的紅包金額和個數。接着下一次再重新計算紅包;
     大致如下,
     max = moneytotal/count*2;
    實際紅包金額= max*Math.random();
    2.4=4*0.6 紅包大小取決於隨機大小(0.1~0.9)之間
*/
public class RedPackageTask {

	 public static BigDecimal getRandomMoney(RedPackage _redPackage) {
	        // remainSize 剩餘的紅包數量
	        // remainMoney 剩餘的錢
	        if (_redPackage.remainSize == 1) {
	            _redPackage.remainSize--;
	            return _redPackage.remainMoney.setScale(2, BigDecimal.ROUND_DOWN);
	        }

	        BigDecimal random = BigDecimal.valueOf(Math.random());
	        BigDecimal min   = BigDecimal.valueOf(0.01);

	        BigDecimal halfRemainSize = BigDecimal.valueOf(_redPackage.remainSize).divide(new BigDecimal(2), BigDecimal.ROUND_UP);
	        BigDecimal max1 = _redPackage.remainMoney.divide(halfRemainSize, BigDecimal.ROUND_DOWN);
	        BigDecimal minRemainAmount = min.multiply(BigDecimal.valueOf(_redPackage.remainSize - 1)).setScale(2, BigDecimal.ROUND_DOWN);
	        BigDecimal max2 = _redPackage.remainMoney.subtract(minRemainAmount);
	        BigDecimal max = (max1.compareTo(max2) < 0) ? max1 : max2;

	        BigDecimal money = random.multiply(max).setScale(2, BigDecimal.ROUND_DOWN);
	        money = money.compareTo(min) < 0 ? min: money;

	        _redPackage.remainSize--;
	        _redPackage.remainMoney = _redPackage.remainMoney.subtract(money).setScale(2, BigDecimal.ROUND_DOWN);;
	        return money;
	    }

	    public static void main(String[] args) {
	    	// 模擬10次搶紅包,每次搶到的數據
	        for (int i = 0; i < 10; i++) {
	            RedPackage moneyPackage = new RedPackage();
	            moneyPackage.remainMoney = BigDecimal.valueOf(1000);//總金額
	            moneyPackage.remainSize = 9;//紅包個數
	            //moneyPackage.remainSize > 0   應該是個數大於0,不然會死循環
	            while (moneyPackage.remainSize != 0) {
	                System.out.print(getRandomMoney(moneyPackage)  + "   ");
	            }
	            System.out.println();
	        }
	        
	        //每次搶的時候生成紅包,實時生成紅包,
	        RedPackage moneyPackage = new RedPackage();
	        //實時紅包就要把remainMoney總金額和remainSize紅包個數設置爲動態,每搶一個就減掉總金額和紅包個數
            moneyPackage.remainMoney = BigDecimal.valueOf(1000);//總金額
            moneyPackage.remainSize = 10;//紅包個數
            //moneyPackage.remainSize > 0   應該是個數大於0,不然會死循環
            if (moneyPackage.remainSize != 0) {
                System.out.print(getRandomMoney(moneyPackage)  + "   ");
            }
            System.out.println();
            
            
	    }

}
class RedPackage {
    int    remainSize;
    BigDecimal remainMoney;
}

參考標準

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章