public static double rand(double money, int people, List<Double> l) {
if (people == 1) {
double red = Math.round(money * 100) / 100.0;
l.add(red+0.01);
return 0;
}
Random random = new Random();
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,最后一个领的一定是手气最佳。