二倍均值算法实现公平抢红包

        假设剩余红包金额为m元,剩余人数为n,那么有如下公式。

每次抢到的金额 = 随机区间 [0.01,m /n × 2 - 0.01]元 这个公式,保证了每次随机金额的平均值是相等的,不会因为抢红包的先后顺 序而造成不公平。

举个例子如下。 假设有5个人,红包总额100元。 100÷5×2 = 40,所以第1个人抢到的金额随机范围是[0.01,39.99]元,在正常 情况下,平均可以抢到20元。 假设第1个人随机抢到了20元,那么剩余金额是80元。 80÷4×2 = 40,所以第2个人抢到的金额的随机范围同样是[0.01,39.99]元,在 正常的情况下,还是平均可以抢到20元。 假设第2个人随机抢到了20元,那么剩余金额是60元。 60÷3×2 = 40,所以第3个人抢到的金额的随机范围同样是[0.01,39.99]元,平 均可以抢到20元。 以此类推,每一次抢到金额随机范围的均值是相等的。 这样做真的是均等的吗?如果第1个人运气很好,随机 抢到39元,第2个人所抢金额的随机区间不就缩减到[0.01,60.99]元了吗? 这个问题提得很好。第1次随机的金额有一半概率超过20 元,使得后面的随机金额上限不足39.99元;但相应地,第1次随机的金额同 样也有一半的概率小于20元,使得后面的随机金额上限超过39.99元。因此从 整体来看,第2次随机的平均范围仍然是[0.01,39.99]元。

/**
 * @program: demo
 * @Description: 抢红包工具类
 * @Author: zwx
 * @Date: 2021/7/19 16:34
 */
public class RedEnvelopeUtils {

    /**
     * 抢红包
     * @method: divideRedPackage
     * @param totalAmount 总金额,以分为单位
     * @param totalPeopleNum 总人数
     * @return {@link List< Integer> }
     * @Author: zwx
     * @Date: 2021/7/19 16:36
     */
        public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum){
        List<Integer> amountList = new ArrayList<Integer>();
         Integer restAmount = totalAmount;
         Integer restPeopleNum = totalPeopleNum;
        Random random = new Random();
        for(int i=0; i<totalPeopleNum-1; i++){
             //随机范围:[1,剩余人均金额的2倍-1] 分
             int amount = random.nextInt(restAmount /
                    restPeopleNum * 2 - 1) + 1;
             restAmount -= amount;
             restPeopleNum --;
             amountList.add(amount);
             }
         amountList.add(restAmount);
         return amountList;
        }

    public static void main(String[] args) {
        //模拟20个人抢100元
        List<Integer> accountList = divideRedPackage(10000, 20);
        for (Integer account : accountList) {
            System.out.println("抢到的金额:"+new BigDecimal(account).divide(new BigDecimal(100)));
        }

    }
}

20个人抢100,打印结果为:

抢到的金额:2.77
抢到的金额:5.28
抢到的金额:5.07
抢到的金额:2.18
抢到的金额:9.87
抢到的金额:8.62
抢到的金额:8.63
抢到的金额:0.41
抢到的金额:7.92
抢到的金额:8.17
抢到的金额:3.06
抢到的金额:0.87
抢到的金额:1.09
抢到的金额:5.49
抢到的金额:6.4
抢到的金额:1.43
抢到的金额:8.38
抢到的金额:6
抢到的金额:6.03
抢到的金额:2.33

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值