微信拼手气红包算法(二倍平均值法)实现示范代码
二倍平均值法
优势在于不需要先把每个人得多少算出来,只有拆红包的时候才会算出这个人得多少,减少实时算力
同时保证了每个人拼手气得到的平均值相同
设有10个人,红包总额100元。
100/10X2 = 20, 所以第一个人的随机范围是(0,20 ),平均可以抢到10元。
假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。
90/9X2 = 20, 所以第二个人的随机范围同样是(0,20 ),平均可以抢到10元。
假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。
80/8X2 = 20, 所以第三个人的随机范围同样是(0,20 ),平均可以抢到10元。
以此类推,每一次随机范围的均值是相等的。
-
截图
-
代码
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
/**
* 微信拼手气红包算法(二倍平均值法)实现示范代码
* @author humorchen
*/
public class RedPackage {
Random random=new Random();
/**
* 每个红包最小金额
*/
BigDecimal min=BigDecimal.valueOf(0.01);
/**
* 将小于1分钱的部分去掉
* @param val
* @return
*/
public BigDecimal floor(BigDecimal val){
return val.setScale(2,RoundingMode.FLOOR);
}
/**
* 根据红包剩余金额和当前剩余红包数计算本次抢红包抢到了多少钱
* @param lastMoney
* @param lastPackage
* @return
*/
public BigDecimal calculate(BigDecimal lastMoney,long lastPackage){
if(lastPackage==1){
return floor(lastMoney);
}
BigDecimal ret=floor(lastMoney.multiply(BigDecimal.valueOf(2*random.nextDouble()))).divide(BigDecimal.valueOf(lastPackage),3,RoundingMode.HALF_DOWN);
if(ret.compareTo(min)==-1){
return min;
}
ret=floor(ret);
return ret;
}
/**
* 给person个人发money元的拼手气红包
* @param money
* @param person
*/
public void sendRedPackage(BigDecimal money,int person){
System.out.println(String.format("红包金额:%s,红包%d个",money.toString(),person));
for (int i=0;i<person;i++){
BigDecimal got=calculate(money,person-i);
System.out.println(String.format("第%d个人拼手气得了%s",(i+1),got.toString()));
money=money.subtract(got);
System.out.println("红包结算后剩余"+money);
}
}
public static void main(String[] args) {
new RedPackage().sendRedPackage(BigDecimal.valueOf(0.04),4);
}
}
本文来自博客园,作者:HumorChen99,转载请注明原文链接:https://www.cnblogs.com/HumorChen/p/18039659