微信红包土豪群包

微信红包的随机算法是怎样实现的?
RT。我考虑了一个简单的算法:比如100元,由10个人分,那么平均一个人是10元钱。然后付款后,系统开始分份儿。第一份:系统由0~10元之间随机一个数,作为这一份的钱数,设x1。第二份:剩下的钱(100-x1),系统由0~(100-x1)/(10-1)随机一个数,作为这份的钱数,设x2.。。。第n份:剩下的钱(100-x1-x2-...-xn),系统由0~(100-x1-x2-...-xn-1)/(10-n)随机一个数,作为这个份的钱数,设为xn当用户进来拿红包的时候,系统由0~9之间随机一个数,随机到几,就取第几份红包,然后将这个数存到list里。当之后的用户抽到相同的随机数时,则将这个数+1,如遇相同再+1,直至list满,红包发完。------------------------------------------------我这么实现可以么??或者大家有更好的办法????
114 个回答
有人问过微信的人,大致是这样:先上代码:public static double getRandomMoney(LeftMoneyPackage _leftMoneyPackage) {
// remainSize 剩余的红包数量
// remainMoney 剩余的钱
if (_leftMoneyPackage.remainSize == 1) {
_leftMoneyPackage.remainSize--;
return (double) Math.round(_leftMoneyPackage.remainMoney * 100) / 100;
= new Random();
double min
= 0.01; //
double max
= _leftMoneyPackage.remainMoney / _leftMoneyPackage.remainSize * 2;
double money = r.nextDouble() *
money = money &= min ? 0.01:
money = Math.floor(money * 100) / 100;
_leftMoneyPackage.remainSize--;
_leftMoneyPackage.remainMoney -=
以上代码仅供参考,涉及商业计算要用java.math.BigDecimal. 感谢 、
指出。再说结论:先抢后抢拿到红包的大小的期望是大致相等的,所以还是先下手抢吧后抢的人方差大(依赖前面人抢的多少),波动较大,有较大几率拿到“手气最佳”祝大家抢红包快乐哦~测试数据。测试结果测试随机红包以上面的初始化数据(30人抢500块),执行了两次,结果如下:// 第一次
对应图表如下:还有一张:多次均值200次2000次可以看到,这个算法可以让大家抢到的红包面额在概率上是大致均匀的。转一下原文微信红包的架构设计简介@来源于QCon某高可用架构群整理,整理朱玉华。背景:有某个朋友在朋友圈咨询微信红包的架构,于是乎有了下面的文字(有误请提出,谢谢)概况:2014年微信红包使用数据库硬抗整个流量,2015年使用cache抗流量。1. 微信的金额什么时候算?答:微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储。采取实时计算金额的考虑:预算需要占存储,实时效率很高,预算才效率低。2. 实时性:为什么明明抢到红包,点开后发现没有?答:2014年的红包一点开就知道金额,分两次操作,先抢到金额,然后再转账。2015年的红包的拆和抢是分离的,需要点两次,因此会出现抢到红包了,但点开后告知红包已经被领完的状况。进入到第一个页面不代表抢到,只表示当时红包还有。3. 分配:红包里的金额怎么算?为什么出现各个红包金额相差很大?答:随机,额度在0.01和(剩余平均值*2)之间。例如:发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动。当前面3个红包总共被领了40块钱时,剩下60块钱,总共7个红包,那么这7个红包的额度在:0.01~(60/7*2)=17.14之间。注意:这里的算法是每被抢一个后,剩下的会再次执行上面的这样的算法(Tim老师也觉得上述算法太复杂,不知基于什么样的考虑)。这样算下去,会超过最开始的全部金额,因此到了最后面如果不够这么算,那么会采取如下算法:保证剩余用户能拿到最低1分钱即可。如果前面的人手气不好,那么后面的余额越多,红包额度也就越多,因此实际概率一样的。4. 红包的设计答:微信从财付通拉取金额数据过来,生成个数/红包类型/金额放到redis集群里,app端将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回。根据红包的逻辑处理成功得到令牌请求,则由财付通进行一致性调用,通过像比特币一样,两边保存交易记录,交易后交给第三方服务审计,如果交易过程中出现不一致就强制回归。5. 发性处理:红包如何计算被抢完?答:cache会抵抗无效请求,将无效的请求过滤掉,实际进入到后台的量不大。cache记录红包个数,原子操作进行个数递减,到0表示被抢光。财付通按照20万笔每秒入账准备,但实际还不到8万每秒。6. 通如何保持8w每秒的写入?答:多主sharding,水平扩展机器。7. 据容量多少?答:一个红包只占一条记录,有效期只有几天,因此不需要太多空间。8. 询红包分配,压力大不?答:抢到红包的人数和红包都在一条cache记录上,没有太大的查询压力。9. 一个红包一个队列?答:没有队列,一个红包一条数据,数据上有一个计数器字段。10.有没有从数据上证明每个红包的概率是不是均等?答:不是绝对均等,就是一个简单的拍脑袋算法。11.拍脑袋算法,会不会出现两个最佳?答:会出现金额一样的,但是手气最佳只有一个,先抢到的那个最佳。12. 每领一个红包就更新数据么?答:每抢到一个红包,就cas更新剩余金额和红包个数。13.红包如何入库入账?数据库会累加已经领取的个数与金额,插入一条领取记录。入账则是后台异步操作。14. 入帐出错怎么办?比如红包个数没了,但余额还有?答:最后会有一个take all操作。另外还有一个对账来保障。原文链接:---我写了代码简单实现了下,大家可以看下:---谢谢阅读!
今年过年我花了120元做了一组实验(其中60元由老婆的红包赞助,特此鸣谢 ^-^ ),获取了两个样本。两个样本的大小均为60人。经过对样本的分析,我的结论是:我赞同土豆的第一条结论,也就是获取的钱数有可能符合截尾正态分布;但不赞同土豆的第二条结论 -- 我的两个样本结果显示,后抽取的人未必获得更多的钱。很有可能腾讯在一个钱包上传时就已经用算法将红包分成了给定份数,接下来抽取人去抽取钱包的时候只是按照时间顺序把给定份数的钱包给抽取人罢了。补充一点:假设陈鹏先生的算法是正确的(亦即此算法确实是微信红包的算法),那么先抽取者与后抽取者获得红包大小的期望值是相同的,但是标准差不同。根据个人的风险偏好的结构(risk preference structure)不同,风险回避(risk-averse)的抽取者应该尽量先抽,而风险偏爱(risk-seeking)的抽取者应该尽量后抽。 【陈鹏先生的算法是否可信以及整体到底符合何种分布都有待于更多的样本进行检验。目前我没有找到反例】以下为验证部分。首先,我来讨论一下为什么要采用截尾正态分布。首先介绍一种更加直接的方法(我有一些朋友也这样猜测):如果我有50元,要发给25人。那么我用连续均匀分布随机产生24个位于0到50之间的数字。这24个数字将整个0-50的区间划分为25份,分别分给这25个人。但事实并不是这样的。学过序列统计的人应该知道,由于这24个点是连续均匀分布产生的,因此他们的序列统计量也是连续均匀分布产生的,因此他们之间的间隔的分布是指数分布的。具体证明从略,可参照John Rice 2007。若是没有序列统计的背景,我们也可以跑一个模拟。我有60元钱,按照上述数据产生机理随机分成60份(因此人均1元左右),然后如是操作10000次,对数据采取聚集后的归一化处理。由于中心极限定理(Central Limit Theorem),该分布反应整体分布(Population Distribution)。画出柱形图如下:可见是符合指数分布的。可见是符合指数分布的。这种产生机理不好的地方在于:大多数人得到的钱非常少,而极少数人得到的钱却非常多,因此可能有一个公平性的问题,而这可能会对抽取人的积极性产生影响。截尾正态分布能够更好地避免这样的问题,因为更多人的红包大小会聚集在平均值附近,而且由于尾部更快的衰减,因此获得特别大的红包的概率也会相应减小,有助于增加公平性与参与的积极性。这一点佐证了土豆的观点,尽管具体截尾的方位可能需要获取更多的数据才有可能有一个准确的预测。以下是我的两个样本的柱形图:大家可以比照我的柱形图与上面指数分布柱形图。注意到:1.更多的人获得的红包在均值附近;2.获取大于2.5元的红包的概率几乎为零(事实上,第一个钱包的最高值是2.06,第二个钱包的最高值是2.10。然而假设是指数分布的(或者说均匀连续分布的数据产生机理),那么在每个60元红包中都会有一定量的抽取者抽到大于3甚至大于4元的红包--这点我通过模拟也确认了。我进一步对正态假设做了检验,如下为样本1,样本2的分位数图(Q-Q Plot)如果完全符合正态分布,那么所有点应该都大致在对角线附近。事实并非完全如此。可见两个样本在一定程度符合正态分布假设,但在两头有一定的异常值。原因有二,一者样本偏小,大数定理不能完全进来,容易有异常值。二者样本是截尾正态分布,所以图和完全正态分布可能有出入。如果完全符合正态分布,那么所有点应该都大致在对角线附近。事实并非完全如此。可见两个样本在一定程度符合正态分布假设,但在两头有一定的异常值。原因有二,一者样本偏小,大数定理不能完全进来,容易有异常值。二者样本是截尾正态分布,所以图和完全正态分布可能有出入。--------------------------------------------------------------------------------------------------------------------------------接下去我讨论一下获取钱包大小和抢钱包先后的关系。我的结论是,红包大小和抢红包先后没有统计意义上的关联。如下是我的两个样本的红包大小数量,我把他们按照时间顺序进行了排序,因此越靠右的人代表越后抢红包的人。如图可见,其实先抢钱包还是后抢钱包对钱包大小的影响未必有很大的影响。事实上,我的两个样本中,抢到的钱数甚至是随着时间推移逐渐减少的,尽管减少的量非常非常小。因此楼上土豆举的例子中向上走的趋势可能是样本特性,不具有普适性。当然了,我也只有两个样本,更进一步的结论或许有待于更多人搜集并贡献钱包的数据。如图可见,其实先抢钱包还是后抢钱包对钱包大小的影响未必有很大的影响。事实上,我的两个样本中,抢到的钱数甚至是随着时间推移逐渐减少的,尽管减少的量非常非常小。因此楼上土豆举的例子中向上走的趋势可能是样本特性,不具有普适性。当然了,我也只有两个样本,更进一步的结论或许有待于更多人搜集并贡献钱包的数据。事实上,如果我们整合第一个结论,腾讯这样的设计是逻辑自洽的。在第一个结论中,我们谈到了截尾分布相比指数分布的优越性在于其公平性。因此,腾讯选择用截尾分布表明了其对公平性的重视。那么,试想这样一个特意选取产生方式更加复杂的截尾分布增加公平性的企业,为什么要让后抢红包的人获得更大的红包呢?这似乎看起来有些自相矛盾。综上所述,我的两个主要结论如下:1)红包大小服从截尾正态分布,其好处是减少抽取红包大小分布的方差,让更多的人抽取的红包在均值附近,同时仍给一小部分人抽取大红包的机会,总体来说增加了红包抽取人的积极性和游戏的公平性;2)抽取红包大小与抽取红包先后无相关性。一种可能的红包产生机制是:当发红包者&准备红包&的时候,程序自动依照截尾分布产生了相应大小,相应个数的红包,然后随机发给抽取红包的人。同样,这样的一个随机过程有助于增加游戏的公平性,也减少了红包抽取人投机操作(亦即譬如故意等钱包半空的时候再抽取)的动机。我在知乎上看到一位朋友谈到她的腾讯工作的朋友确认了红包产生是在&准备红包&时就完成了的,因此也在一定程度上增强了我的这种推测的可信度。-------------------------------------------------------------------------------------------------------------------------------PS: 我看到知友陈鹏先生贴上了微信的算法。我用陈先生的算法研究了一下抢红包的人抢到红包大小和抢红包先后的关系,想与大家分享一下研究结果。陈鹏先生的代码大致意思是这样的:假设有100元钱,分给十个人。那么第一个人获得红包大小怎么计算呢?100/10 = 10元。这是期望值。从0.01到20的区间中(其中20=10乘以2)随机抽取一个数,就是第一个人获得红包的大小。假设第一个人获得了15元,那么剩下的85元平均分给9个人,这九个人平均获得红包大小为9.4元,那么第二个人的红包大小均匀分布于0.01元到18.80元的区间中,依次类推。算法保证最后一个人至少抽到0.01元。不难看出,每个人获得的红包大小的期望值仍然是10元。但是分布就不同了,因为之前抽取的人结果的好坏会影响到后抽取的人的结果。假设陈鹏先生贴的算法是可靠的,亦即微信确实用这样的算法来分配红包,我简单模拟了一下第一个抽取的人,第五个抽取的人,以及最后一个抽取的人(第十人)的红包大小的分布如下:如图显见,对于第一个抽取红包的人,抽取红包大小服从均匀分布,但越到后面的抽取者抽取红包大小的分布就越不均匀。越到后面的抽取者越有可能抽到小的红包,但也有可能抽到一个数值相当大的红包。理论上讲,加入前九个人运气都很差并都只抽到0.01,最后一个人抽取红包的数额可能接近100。当然,均匀分布下这类情况出现的可能性几乎为零,经过我反复验证,100,000次中都不会出现一次。我同时附上抽取红包的期望值大小以及标准差大小的表格。如图显见,对于第一个抽取红包的人,抽取红包大小服从均匀分布,但越到后面的抽取者抽取红包大小的分布就越不均匀。越到后面的抽取者越有可能抽到小的红包,但也有可能抽到一个数值相当大的红包。理论上讲,加入前九个人运气都很差并都只抽到0.01,最后一个人抽取红包的数额可能接近100。当然,均匀分布下这类情况出现的可能性几乎为零,经过我反复验证,100,000次中都不会出现一次。我同时附上抽取红包的期望值大小以及标准差大小的表格。简单地说,结论就是:简单地说,结论就是:假设陈鹏先生贴的算法是可靠的,那么风险规避(risk-averse)的红包抽取人应该尽量抢先抽取,而风险偏爱(risk-seeking)的红包抽取人应该尽量后抽取(而且越往后似乎标准差增速也越大),因为后抽者取有可能抽到先抽取者不可能抽到的大红包,尽管抽到小红包的概率也会相应增大。Most of the things of this world are about trade-off, and there is just no such thing as a free lunch. 最后附上我发的两个红包所获取的原始数据,这样有兴趣的研究猿可以在我的基础上做进一步调查与研究。祝大家猴年吉祥,万事胜意!
楼上大多数人都是在做出自己的猜测,这也是在不知道内部随机算法的时候的唯一选择,但是大多数人没有给出自己亲自的调查结果。这里给出一份100样本的调查抽样样本数据,并提出自己的猜测。1.
钱包钱数满足截尾正态随机数分布。大致为在截尾正态分布中取随机数,并用其求和数除以总价值,获得修正因子,再用修正因子乘上所有的随机数,得到红包价值。
这种分布意味着:低于平均值的红包多,但是离平均值不远;高于平均值的红包少,但是远大于平均值的红包偏多。图1. 钱包价值与其频率分布直方图及其正态拟合
但看分布直方图并不能推出它符合正态分布,但是考虑到程序的简洁性和随机数的合理性,这是最合乎情理的一种猜测。2.
越是后面的钱包,价值普遍更高图2. 钱包序列数与其价值关系曲线
从图2中的线性拟合红线可以看到,钱包价值的总体变化趋势是在慢慢增大,其变化范围大约是一个绿色虚线上下界划出的“通道”。(曲线可以被围在这么一个正合乎常规的“通道”中,也从侧面反映了规律1的合理性,说明了并不是均匀分布的随机数)
从另一个平均数的图中也可以看出这一规律。图3. 平均数随序列数的变化曲线在样本中,1000价值的钱包被分成100份,均值为10。然而在图3中我们可以看到在最后一个钱包之前,平均数一直低于10,这就说明了一开始的钱包价值偏低,一直被后期的钱包价值拉着往上走,后期的钱包价值更高。3.
当然平均数的图还可以透露出另一个规律,那就是最后的那一个人往往容易走运抽得比较多。因为最后那一个人是钱包剩下多少就拿多少的,而之前所有人的平均数都低于10,所以至少保证了最后一个人会高于平均值。在本样本中,98号钱包抽到35,而最后一份钱包抽到46。综上,根据样本猜测:1.
抽到的钱大多数时候跟别人一样少,但一旦一多,就容易多很多。2.
越是抽后面的钱包,钱越容易多。3.
最后一个人往往容易撞大运。
其实这些一点用的没有,就是自己闲了无聊开一开脑洞,大家别认真,玩红包开心就好哈哈,土豆祝大家新年快乐啦~
——Potato
红包抢了很多,有种错觉,就是最后那一两个红包总是最佳手气。为了分析红包多少的分布,取了红包数量 &= 5 的 100 个红包,,其中红包份数为 5 份、10份和 20 份的占了 2/3(66 个),最多的一个红包有 22 份,这 100 个红包的份数分布如下:5:
——————
对每个红包 i ,统计分布。其中
为第 i 个抢到的钱数, 为红包总金额, 为红包平均金额。把结果再平均一下,得到下图:结论就是我想多了……
据观察,红包分钱满足以下几点:不会有人拿不到钱不会提前分完钱的波动范围很大 的答案我完全同意。红包在一开始创建的时候,分配方案就订好了。抢红包的时候,不过是挨个pop up而已。针对他说的算法二写个 python 代码。def weixin_divide_hongbao(money, n):
divide_table = [random.randint(1, 10000) for x in xrange(0, n)]
sum_ = sum(divide_table)
return [x*money/sum_ for x in divide_table]
不过上述算法还有两个小问题:浮点数精度问题边界值的处理不过,都是很容易解决的小问题,你们看的是算法思想,对吧。
家里的中老年人抢得很开心,就用他们发红包的形式模拟了一下微信红包收益期望与拆开顺序的关系。说明:1. 未考虑“手气最佳或手气最背者须再发红包”等对收益的影响。2. 以所提供的红包算法为准。3. 以总金额20元,6个红包为例。结果:说明:期望值可理解为该玩家抢无穷多次红包后得到的平均金额。标准差可理解为风险大小,标准差越大,与期望值相比,就越有可能抢到一个较大/较小的红包。根据所参考的红包分配算法,最后两名的期望情况是一模一样的,这是容易理解的,这也或许就是该算法的设计初衷。故第二、三名的期望值较为高,五、六名的期望值较为低。总体差异不大,最大值与最小值相差不超过一分钱,即一百次红包后,相差不超过一元钱。越靠后的玩家标准差越大,风险越大。(最后两名情况一样。)概率密度曲线在金额较低时基本为水平直线,符合算法设计。时间仓促,仅供娱乐。其实我不大相信这个算法的真实程度。日Andrew ZHI HFLS
我们昨天几个人讨论了一晚上。题主算法的问题是,有可能有一个人一下子把所有钱拿走了,而其他人都没有得到钱。然后按照我对现在发出去和别人发的红包的观察,认为算法应该满足以下几个条件:1、不能一个人一下子把钱拿走,也就是有预留额;2、一个人拿到极小数(比如0.01元)的概率远大于拿到极大数(99%的总额)的概率;3、多数人都是在平均数附近浮动的。为了满足这几个条件,我提出一个算法假设:1、使用偏正态分布产生各个红包;2、有人为的红包上限设置,也即最大的红包不超过平均值的k倍,k的数值与红包个数n有关,同时也受到红包平均数money/n这个绝对值的制约;采用这个算法的话,获得的红包同现在的情况比较符合。但是对于算法的第二点,我还无法做出更好的猜测,因为本人和朋友发红包的数量不多,无法做出基于大样本的猜测。
微信红包的架构设计简介@来源于QCon某高可用架构群整理,整理朱玉华。背景:有某个朋友在朋友圈咨询微信红包的架构,于是乎有了下面的文字(有误请提出,谢谢)概况:2014年微信红包使用数据库硬抗整个流量,2015年使用cache抗流量。微信的金额什么时候算? 答:微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储。。 采取实时计算金额的考虑:预算需要占存储,实时效率很高,预算才效率低。实时性:为什么明明抢到红包,点开后发现没有? 答:2014年的红包一点开就知道金额,分两次操作,先抢到金额,然后再转账。 2015年的红包的拆和抢是分离的,需要点两次,因此会出现抢到红包了,但点开后告知红包已经被领完的状况。进入到第一个页面不代表抢到,只表示当时红包还有。分配:红包里的金额怎么算?为什么出现各个红包金额相差很大? 答:随机,额度在0.01和剩余平均值*2之间。 例如:发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动。当前面3个红包总共被领了40块钱时,剩下60块钱,总共7个红包,那么这7个红包的额度在:0.01~(60/7*2)=17.14之间。 注意:这里的算法是每被抢一个后,剩下的会再次执行上面的这样的算法(Tim老师也觉得上述算法太复杂,不知基于什么样的考虑)。这样算下去,会超过最开始的全部金额,因此到了最后面如果不够这么算,那么会采取如下算法:保证剩余用户能拿到最低1分钱即可。如果前面的人手气不好,那么后面的余额越多,红包额度也就越多,因此实际概率一样的。红包的设计 答:微信从财付通拉取金额数据郭莱,生成个数/红包类型/金额放到redis集群里,app端将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回。根据红包的裸祭处理成功得到令牌请求,则由财付通进行一致性调用,通过像比特币一样,两边保存交易记录,交易后交给第三方服务审计,如果交易过程中出现不一致就强制回归。发性处理:红包如何计算被抢完? 答:cache会抵抗无效请求,将无效的请求过滤掉,实际进入到后台的量不大。cache记录红包个数,原子操作进行个数递减,到0表示被抢光。财付通按照20万笔每秒入账准备,但实际还不到8万每秒。通如何保持8w每秒的写入? 答:多主sharding,水平扩展机器。据容量多少? 答:一个红包只占一条记录,有效期只有几天,因此不需要太多空间。询红包分配,压力大不? 答:抢到红包的人数和红包都在一条cache记录上,没有太大的查询压力。一个红包一个队列? 答:没有队列,一个红包一条数据,数据上有一个计数器字段。有没有从数据上证明每个红包的概率是不是均等? 答:不是绝对均等,就是一个简单的拍脑袋算法。拍脑袋算法,会不会出现两个最佳? 答:会出现金额一样的,但是手气最佳只有一个,先抢到的那个最佳。每领一个红包就更新数据么? 答:每抢到一个红包,就cas更新剩余金额和红包个数。红包如何入库入账? 数据库会累加已经领取的个数与金额,插入一条领取记录。入账则是后台异步操作。入帐出错怎么办?比如红包个数没了,但余额还有? 答:最后会有一个take all操作。另外还有一个对账来保障。
我觉得这个问题的合理解有两个目标:1. 不要出现人为的阈值,比如预留值、最大和最少量、切割比例等拍脑袋的数据。2.尽量贴近过年的喜庆气氛,不要出现太多或者太少的情况。如果有什么其它考虑,方便实现成代码也算一个。所以我的思路其实用一句话就可以概括:生成n(n是总人数)个(0,1]之间的随机数,然后将其求和被Q(Q是总钱数)除得到一个比例C,用C乘以所有数,这样就得到了最终结果。这个算法很多人都会想到,但是被大家抛弃的原因应该在于随机性太大。那么我想到的修正方案:生成随机数时不要采用平均分布的随机数,而用正态分布的随机数。可是系统提供的随机数算法基本都是基于平均分布的,那现在提供一个平均分布映射到正态分布的算法就可以了。其实这个算法很常见,假设生成的平均分布数是x,正态分布所求值是y,正太分布表达式是f(y),那么f(y)求积分记为F(y),根据这样一个式子F(y) = x,求出F(y)的反函数就是所需要的映射函数。这个看起来很复杂,其实求出一个式子后代码写起来很简单。原谅我的数学表达基本已经都忘了,如果有写错,欢迎指正。所以这个算法只需要两个function就可以实现,下面是个伪代码 :double generateRandomNumber(){
//generate random number based on normal distribution}void process(double totalMoney, int personNum){
double[personNum]
for (int i=0; i & personN i++){
results[i] = generateRandomNumber();
double ratio = totoalMoney/sum(results);
for (int i=0; i & personN i++){
results[i] = result[i] *
}}PS:这个算法的生产随机数其实是可配置的,取决于开发者希望最终趋近于什么样的分布,只要找到其和平均分布的映射关系,就可以使用什么样的生成算法。PPS:这个分布算法如果能让用户配置会更好玩,比如配置成1个人领50%,3个人领30%,剩下的人分20%,还会有抽大奖的感觉,哈哈哈~
从工程角度来说,红包分配算法需要简单粗暴的实现。楼上有人的算法过于复杂,第几个人领取都要面面俱到的计算,考虑因素太多,工程实现上真的没必要。其实只需要按照如下框架即可:1. 发红包时,按照设计的快速随机算法,将红包分好若干份。2. 按照设计的评估算法,对得到的红包分配进行校验。3. 如果校验不通过,如贫富差距过大,则重复随机分配。4. 如果若干次重复,如5次,则停止重复,就按照当前分配。5. 再有用户请求红包,直接队列化请求,再从红包序列中取出对应编号红包。上述方案的优势是:1. 只需“一次”计算。随机算法选择简单粗暴的即可,系统按照校验策略对其评价,不满足则有限次重复,直到满足或次数太多为止。2. 此后就只有读取。后续操作完全是读取缓存,无需密集计算。那么是不是还有更简单粗暴的方案呢?还是有的,那就是伪随机序列查表法。百万千万级别的红包请求,如果每次都按照真随机来计算,仍然会有不小的计算压力。索性预先计算得到若干伪随机分配方案,调用时只需要随机选择一个即可。举例来说,有人的红包是10元分配给5人,系统预先存有多种分配方案,如1,1,2,3,3,或1,1,2,2,4,请求时随机选取一个方案即可。当然,各种组合未必能穷尽,但是只需要让用户在有限次操作中觉得这是随机就够了。
已有帐号?
无法登录?
社交帐号登录

我要回帖

更多关于 微信红包群 的文章

 

随机推荐