然而我之前的代码却没办法体现出这一点。
比如 10 人拆 0.11 元的包,我的结果是:
可见以上代码还存在不足之处。
于是我就有一个猜测:
微信可能不是对全金额进行随机的,可能在派发红包之前,已经对金额做了处理,比如,事先减去(红包个数*0.01),之后在每个红包的随机值基础上加 0.01,以此来保证每个红包最小值都是 0.01。
这个猜测或许可以解开那位知友和我哥们这边的疑惑。
5.4、完善算法在原先的基础上对代码进行简单的修正:
public static double rand(double money, int people, List l) {
if(people == 1) {
double red = Math.round(money * 100) / 100.0;
l.add(red 0.01);
return 0;
}
Random random = newRandom();
double min = 0;
double max = money / people * 2.0;
double red = random.nextDouble() * max;
red = red <= min ? min : red;
red = Math.floor(red * 100) / 100.0;
l.add(red 0.01);
double remain = Math.round((money – red) * 100) / 100.0;
return remain;
}
这个算法,在第一次调用时传入 money 的值是总金额减去红包数*0.01,大概像这样:
_money = _money – people * 0.01;
5.5、第二次分析 5.5.1 验证上次的不足之处1)10 人抢 0.11 元的包:
2)2 人抢 0.03 元的包:
3)6 人抢 0.09 的包:
5.5.2 修改后的代码会不会对已知结论造成影响?30 元的红包,10 人抢,操作 100 次。
▲ x轴为抢的顺序,y轴为该次抢到金额
▲ x轴为抢的顺序,y轴为该次抢到金额重复 100 次后的平均值
由上面两图可见,结论基本上没有改变。
5.6、结论经过上述代码实践可知:
1)先抢后抢,金额期望都是相同的;
2)微信的红包算法很可能是预先分配给每人 0.01 的“底额”;
3)后抢者风险高,收益大。
5.7、补充上几张后面测试的图,补充一下之前的观点,发 n 个红包,总金额是(n 1)*0.01,最后一个领的一定是手气最佳。
大家也可以试试。
以上,大概可以证明,微信红包是在分配前先给每个人 0.01 的最低金额的!
6、参考资料[1] 微信红包随机算法初探
[2] 微信红包算法的分析
[3] 微信红包的架构设计简介
[4] 微信红包的随机算法是怎样实现的?