注册 留言板
当前位置:首页 > 编程语言 > Ruby/Rails > 正文

Ruby微信红包分配算法

来源:INFOCOOL   发布时间: 2016-06-05   作者:网友   浏览次数:
摘要: 今年和去年一样,央视的春晚再次被广大网友吐槽, 即便全民呼吁“六小龄童上春晚”,齐天大圣仍然没有走上央视舞台。知名时评...

今年和去年一样,央视的春晚再次被广大网友吐槽, 即便全民呼吁“六小龄童上春晚”,齐天大圣仍然没有走上央视舞台。知名时评人石述思转了这样一条微博,今年的春晚导演为了大家抢红包也是拼了,连一分钟好看的节目都没安排。目前全国人民都听牌了,单吊敬业福!

 

    稍微吐槽一下还是回到今天的主题,微信红包金额分配算:知乎上的一篇文章讨论的比较深入,个人觉得下面的这个分析比较靠谱。

 

红包领了不少,据观察红包主要有以下几个限制条件:

1.所有人都能分到红包,也就是不会出现红包数值为0的情况。

2.所有人的红包数值加起来等于支付的金额。

3.红包波动范围比较大,约5%~8%的红包数值在平均值的两倍以上,同时数额0.01出现的概率比较高。

4.红包的数值是随机的,并且数值的分布近似于正态分布。

 

基本思路:
 

1.因为要保证每个人都至少抢到一分钱,那么首先给每个人分配1分钱

2.剩下的钱再随机分给每个人,Ruby的随机函数是平均分布的,因此如果需要使红包金额近似正态分布,需要对平均分布进行Box–Muller转换操作

3.由于精度问题,最后一个红包需要用总的红包金额-已分配的金额

4. 得到服从正态分布的随机数的基本思想是先得到服从均匀分布的随机数,再将服从均匀分布的随机数转变为服从正态分布

 

Box-Muller
 

    Box-Muller是产生随机数的一种方法。Box-Muller算法隐含的原理非常深奥,但结果却是相当简单。

如果在(0,1]值域内有两个一致的随机数字U1和U2,

可以使用以下两个等式中的任一个算出一个正态分布的随机数字Z:

Z=R*cos(θ)或Z=R*sin(θ)

其中,R=sqrt(-2*ln(U2));θ=2*π*U1

正态值Z有一个等于0的平均值和一个等于1的标准偏差,可使用以下等式将Z映射到一个平均值为m、标准偏差为sd的统计量X:

X=m+(Z*sd)

 

mu和sigma值的确定:
 

mu的值:

为当前红包的均值,令分配第i个红包时所剩总金额为Ti,所以:Ti = T - 0.01 * k - a0 - … - ai-1

得到:mu = Ti / (k - i)

 

sigma的值:

 sigma 的值会直接影响红包数额的分布曲线,根据正态分布的三个sigma定理, 生成的随机数值有95.449974%几率落在(mu-2*sigma,mu+2*sigma)内,为了使得mu-2*sigma = 0,sigma = mu/2。对于生成的随机数落在[0, Ti]以外区间的情况,采用截断处理,统一返回0或者Ti。也就是说,最后生成的随机数值分别有大约6%的几率为0或者大于2*mu,加上保留的0.01

rg = RandomGaussian.new(mu,sigma)

noiseValue = rg.rand.round(2)

 

测试:
 

generateMoneyVector(1, 3)

[0.42, 0.38, 0.2]

[0.49, 0.06, 0.45]

[0.18, 0.54, 0.28]

generateMoneyVector(1, 10)

[0.13, 0.11, 0.08, 0.13, 0.01, 0.11, 0.04, 0.15, 0.16, 0.08]

[0.07, 0.12, 0.11, 0.15, 0.08, 0.05, 0.14, 0.18, 0.03, 0.07]

[0.12, 0.08, 0.15, 0.10, 0.11, 0.04, 0.04, 0.10, 0.05, 0.21]



ruby 信红包
我来说两句
评论内容:
验  证  码:
 
(网友评论仅供其表达个人看法,并不表明本站同意其观点或证实其描述。)
评论列表
已有 0 条评论(查看更多评论)
精彩专题
友情链接:
QQ交流群:①群 155252576 ②群 469193068 ③群 531831996 ④群 243504572
设为首页 - 加入收藏 Copyright @2016 Infocool 版权所有 粤ICP备16000626号