微信红包的随机算法是怎样实现的?

如题所述

第1个回答  2018-01-02
‍‍‍‍

1. 钱包钱数满足截尾正态随机数分布。大致为在截尾正态分布中取随机数,并用其求和数除以总价值,获得修正因子,再用修正因子乘上所有的随机数,得到红包价值。这种分布意味着:低于平均值的红包多,但是离平均值不远;高于平均值的红包少,但是远大于平均值的红包偏多。但看分布直方图并不能推出它符合正态分布,但是考虑到程序的简洁性和随机数的合理性,这是最合乎情理的一种猜测。

2. 越是后面的钱包,价值普遍更高,线性拟合红线可以看到,钱包价值的总体变化趋势是在慢慢增大,其变化范围大约是一个绿色虚线上下界划出的“通道”。(曲线可以被围在这么一个正合乎常规的“通道”中,也从侧面反映了规律1的合理性,说明了并不是均匀分布的随机数)。

3. 当然还可以透露出另一个规律,那就是最后的那一个人往往容易走运抽得比较多。因为最后那一个人是钱包剩下多少就拿多少的,而之前所有人的平均数都低于10,所以至少保证了最后一个人会高于平均值。在本样本中,98号钱包抽到35,而最后一份钱包抽到46。综上,根据样本猜测:

1. 抽到的钱大多数时候跟别人一样少,但一旦一多,就容易多很多。

2. 越是抽后面的钱包,钱越容易多。

3. 最后一个人往往容易撞大运。

‍‍‍‍
第2个回答  2018-01-02
‍‍

我觉得这个问题的合理解有两个目标:

1. 不要出现人为的阈值,比如预留值、最大和最少量、切割比例等拍脑袋的数据。

2.尽量贴近过年的喜庆气氛,不要出现太多或者太少的情况。如果有什么其它考虑,方便实现成代码也算一个。所以我的思路其实用一句话就可以概括:生成n(n是总人数)个(0,1]之间的随机数,然后将其求和被Q(Q是总钱数)除得到一个比例C,用C乘以所有数,这样就得到了最终结果。这个算法很多人都会想到,但是被大家抛弃的原因应该在于随机性太大。那么我想到的修正方案:生成随机数时不要采用平均分布的随机数,而用正态分布的随机数。可是系统提供的随机数算法基本都是基于平均分布的,那现在提供一个平均分布映射到正态分布的算法就可以了。其实这个算法很常见,假设生成的平均分布数是x,正态分布所求值是y,正太分布表达式是f(y),那么f(y)求积分记为F(y),根据这样一个式子F(y) = x,求出F(y)的反函数就是所需要的映射函数。这个看起来很复杂,其实求出一个式子后代码写起来很简单。原谅我的数学表达基本已经都忘了,如果有写错,欢迎指正。这个算法的生产随机数其实是可配置的,取决于开发者希望最终趋近于什么样的分布,只要找到其和平均分布的映射关系,就可以使用什么样的生成算法。PPS:这个分布算法如果能让用户配置会更好玩,比如配置成1个人领50%,3个人领30%,剩下的人分20%,还会有抽大奖的感觉,哈哈哈~

‍‍
第3个回答  2018-01-02
‍‍

核心算法就是随机数主要的需求是得出10个红包,同时有一个隐性条件,每个红包中都要有钱,即每个红包至少1分钱。如果是我会这么干(100块分成10个红包),先取10分钱出来,这样可以屏蔽有的红包没钱的问题。剩下9990分钱,把这9990分钱分成10份即可。9990分钱一字排开,用9块板子插到这些钱中间(插板子这事你们肯定都干过),每两块板子中有多少钱就是一个红包中的钱数了,再加上之前取出的1分钱就是最后的红包了。怎么找插板子的位置呢?取0到1之间的随机数乘9991就好了,重复做9次。第1块板之前的钱加1分就是第一个红包里的钱数,依此类推得出10个红包中的钱数。之后要测试这种方法是不是平均的分了。分个一万次,嗯,反正电脑不会累。回答完毕。微信的红包表现还挺好的 也就卡个10来分钟。。。想发的可以先塞钱,过10分钟再发。

‍‍