《PHP应用:大家在抢红包,程序员在研究红包算法》要点:
本文介绍了PHP应用:大家在抢红包,程序员在研究红包算法,希望对您有用。如果有疑问,可以联系我们。
大年节全天微信用户红包总发送量达到10.1亿次,摇一摇互动量达到110亿次,红包峰值发送量为8.1亿次/分钟.PHP教程
抛开微信红包的市场价值不谈,红包自己的算法也引发了热议,由于官方没有给出明确的说法,各家也是众说纷纭,小编下面也为大家带来几种分析.PHP教程
首先看看数据阐发帝PHP教程
大多数人都做出本身的猜测,这也是在不知道内部随机算法的时候的唯一选择,但是大多数人没有给出本身亲自的调查结果.这里给出一份100样本的调查抽样样本数据,并提出本身的猜测.
PHP教程
1. 钱包钱数满足截尾正态随机数分布.年夜致为在截尾正态分布中取随机数,并用其求和数除以总价值,获得修正因子,再用修正因子乘上所有的随机数,得到红包价值.PHP教程
这种分布意味着:低于平均值的红包多,但是离平均值不远;高于平均值的红包少,但是远年夜于平均值的红包偏多.PHP教程
PHP教程
图1. 钱包代价与其频率分布直方图及其正态拟合
PHP教程
但看分布直方图并不克不及推出它符合正态分布,但是考虑到程序的简洁性和随机数的合理性,这是最合乎情理的一种猜测.
越是后面的钱包,价值普遍更高
PHP教程
PHP教程
图2. 钱包序列数与其代价关系曲线PHP教程
从图2中的线性拟合红线可以看到,钱包价值的总体变化趋势是在慢慢增大,其变化范围大约是一个绿色虚线上下界划出的“通道”.(曲线可以被围在这么一个正合乎常规的“通道”中,也从侧面反映了规律1的合理性,阐明了并不是均匀分布的随机数)
从另一个平均数的图中也可以看出这一规律.
PHP教程
PHP教程
图3. 平均数随序列数的变化曲线PHP教程
在样本中,1000价值的钱包被分成100份,均值为10.然而在图3中我们可以看到在最后一个钱包之前,平均数一直低于10,这就阐明了一开始的钱包价值偏低,一直被后期的钱包价值拉着往上走,后期的钱包价值更高.PHP教程
3. 当然平均数的图还可以透露出另一个规律,那就是最后的那一个人往往容易走运抽得比拟多.因为最后那一个人是钱包剩下多少就拿多少的,而之前所有人的平均数 都低于10,所以至少保证了最后一个人会高于平均值.在本样本中,98号钱包抽到35,而最后一份钱包抽到46.PHP教程
综上,根据样本猜测:
PHP教程
PHP教程
1. 抽到的钱年夜多数时候跟别人一样少,但一旦一多,就容易多很多.
2. 越是抽后面的钱包,钱越容易多.
3. 最后一个人往往容易撞年夜运.PHP教程
点评:这种明显很实际有差别,小编每次不管什么时候抢都是几毛钱.
PHP教程
第二位同学写了一个简单python 代码
PHP教程
据察看,红包分钱满足以下几点:PHP教程
1.不会有人拿不到钱
PHP教程
2.不会提前分完
PHP教程
3.钱的波动范围很年夜
PHP教程
红包在一开始创建的时候,分配方案就订好了.抢红包的时候,不过是挨个pop up罢了.
PHP教程
因此 python 代码如下:PHP教程
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]
不外上述算法还有两个小问题:PHP教程
1.浮点数精度问题
PHP教程
2.界限值的处理PHP教程
第三位同学依照网上流传的python写了一个java的版本PHP教程
int j=1; while(j<1000) { int number=10; float total=100; float money; double min=0.01; double max; int i=1; List math=new ArrayList(); while(i<number) { max = total- min*(number- i); int k = (int)((number-i)/2); if (number -i <= 2) {k = number -i;} max = max/k; money=(int)(min*100+Math.random()*(max*100-min*100+1)); money=(float)money/100; total=total-money; math.add(money); System.out.println("第"+i+"个人拿到"+money+"剩下"+total); i++; if(i==number) { math.add(total); System.out.println("第"+i+"个人拿到"+total+"剩下0"); } } System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气最佳"); j++; }
第四位同学的这种算法看起来非常科学.
PHP教程
他认为:
PHP教程
1、每个人都要能够领取到红包;
PHP教程
2、每个人领取到的红包金额总和=总金额;
PHP教程
3、每个人领取到的红包金额不等,但也不能差的太离谱,不然就败兴味;
PHP教程
4、算法必定要简单,不然对不起腾讯这个招牌;
PHP教程
正式编码之前,先搭建一个递进的模型来阐发规律
PHP教程
设定总金额为10元,有N个人随机领取:
PHP教程
N=1
PHP教程
则红包金额=X元;
PHP教程
N=2
PHP教程
为保证第二个红包可以正常发出,第一个红包金额=0.01至9.99之间的某个随机数
PHP教程
第二个红包=10-第一个红包金额;
PHP教程
N=3
PHP教程
红包1=0.01至0.98之间的某个随机数
PHP教程
红包2=0.01至(10-红包1-0.01)的某个随机数
PHP教程
红包3=10-红包1-红包2
PHP教程
……
PHP教程
int j=1; while(j<1000) { int number=10; float total=100; float money; double min=0.01; double max; int i=1; List math=new ArrayList(); while(i<number) { max = total- min*(number- i); int k = (int)((number-i)/2); if (number -i <= 2) {k = number -i;} max = max/k; money=(int)(min*100+Math.random()*(max*100-min*100+1)); money=(float)money/100; total=total-money; math.add(money); System.out.println("第"+i+"个人拿到"+money+"剩下"+total); i++; if(i==number) { math.add(total); System.out.println("第"+i+"个人拿到"+total+"剩下0"); } } System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气最佳"); j++; }
输入一看,波动太年夜,这数据太无趣了!
PHP教程
第1个红包:7.48 元,余额:2.52 元
PHP教程
第2个红包:1.9 元,余额:0.62 元
PHP教程
第3个红包:0.49 元,余额:0.13 元
PHP教程
第4个红包:0.04 元,余额:0.09 元
PHP教程
第5个红包:0.03 元,余额:0.06 元
PHP教程
第6个红包:0.03 元,余额:0.03 元
PHP教程
第7个红包:0.01 元,余额:0.02 元
PHP教程
第8个红包:0.02 元,余额:0 元
PHP教程
改良一下,将平均值作为随机平安上限来控制波动差
PHP教程
int j=1; while(j<1000) { int number=10; float total=100; float money; double min=0.01; double max; int i=1; List math=new ArrayList(); while(i<number) { max = total- min*(number- i); int k = (int)((number-i)/2); if (number -i <= 2) {k = number -i;} max = max/k; money=(int)(min*100+Math.random()*(max*100-min*100+1)); money=(float)money/100; total=total-money; math.add(money); System.out.println("第"+i+"个人拿到"+money+"剩下"+total); i++; if(i==number) { math.add(total); System.out.println("第"+i+"个人拿到"+total+"剩下0"); } } System.out.println("本轮发红包中第"+(math.indexOf(Collections.max(math))+1)+"个人手气最佳"); j++; }
输出成果见下图PHP教程
第1个红包:0.06 元,余额:9.94 元
PHP教程
第2个红包:1.55 元,余额:8.39 元
PHP教程
第3个红包:0.25 元,余额:8.14 元
PHP教程
第4个红包:0.98 元,余额:7.16 元
PHP教程
第5个红包:1.88 元,余额:5.28 元PHP教程
第6个红包:1.92 元,余额:3.36 元
PHP教程
第7个红包:2.98 元,余额:0.38 元
PHP教程
第8个红包:0.38 元,余额:0 元
PHP教程
小结:
PHP教程
小编觉得这完全可以理解成一个红包引发的血案,小编仅仅列举了几个,还有一些工程学的同学直接抛出了数学模型、离散函数等等,然则无论算法是简单还是复杂,玩的开心就够了.PHP教程
欢迎参与《PHP应用:大家在抢红包,程序员在研究红包算法》讨论,分享您的想法,维易PHP学院为您提供专业教程。
转载请注明本页网址:
http://www.vephp.com/jiaocheng/8758.html