前言

面试,或者社会,网络,甚至电视上都会谈到的一个问题, 关于微信红包是否每个人都概率一样的问题, 于是在数学上做了一个证明,并写了个程序验算了公式

提出想法

脑子里第一个想法就是: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/93148https://cloud.tencent.com/developer/article/1699931https://www.zhihu.com/question/22625187