前言
面试,或者社会,网络,甚至电视上都会谈到的一个问题,
关于微信红包是否每个人都概率一样的问题,
于是在数学上做了一个证明,并写了个程序验算了公式
提出想法
脑子里第一个想法就是:m1 = rand(0.01, m - 0.01*n),其中:
rand: 随机函数
m1: 抢到的金额
m: 当前钱包剩余金额
n: 当前还未抢红包的人数
意思就是,每次抢到的钱包金额是保证剩余的人至少能抢包1分钱之后,剩余的金额随机抢一个金额,
相信大多数人的第一反应就是这一个意思,这样是对的吗?
数学来了
从数学角度可以证明,这样是不平均的,证明如下:
定义M为总金额,
第一次抢红包的金额为, m1 = [0.01, M), 平均金额金额为 m1 = M/2
第二次抢红包的金额为,m = M - m1, m2 = [0.01, m), 平均金额为 m2 = (M - m1) / 2 = M/4
同理,
第三次抢红包的金额为,m = M - m1 - m2, m3 = [0.01, m),平均金额为 m3 = (M - m1 - m2) / 2 = M/8
...
第n次平均金额为 mn = (M - m1 - m2 - ... - mn-1) / 2
由上易得:
m1 = M/2 > m2 = M/4,
m2 = M/4 > m3 = M/8
...
也可以得 m = M/(2^n),
当n增大时,m减小。可知m是关于n一个单调递减函数。
得出结论,先抢到的期望大于后面的期望值,抢到的红包金额不平均,由此特地写一个程序证明:
100块钱,10个红包,循环了10000次,平均值如下:
上面图标金额单位是分,总额为9995分,丢的5分是因为每次的金额除以10000时,整数丢精度了,没处理,但是所有抢到的总金额是正确的。这个不影响结论,所以忽略误差的5分钱。
可以明显看到测试后的数据满足公式推论,上一次是下一次的2倍。但是最后的几次不满足。原因是因为红包最后一次有一个pick all的操作,即是第10个人,不管剩余多少,都全部是第10个人的。
正确的算法来了
根据参考文章提到的红包算法公式:m1 = rand(0.01, (m/n)*2)
, 其中,
rand: 随机函数
m1: 抢到的金额
m: 当前钱包剩余金额
n: 当前还未抢红包的人数
简单证明:
第一次抢红包的平均金额是 m1 = M/n,
第二次抢红包的平均金额是 m2 = M/n,
第三次抢红包的平均金额是 m3 = M/n,
...
第n次抢红包的平均金额是 mn = M/n,
即:
无论第几次抢红包,抢到的红包的平均值都是M/n.
这才使得红包分部均匀,先抢还是后抢都是一样的期望值。
这个没有写程序了,在该文章中有程序证明:
参考文章:
- https://www.zybuluo.com/yulin718/note/93148
- https://cloud.tencent.com/developer/article/1699931
- https://www.zhihu.com/question/22625187