《PHP應(yīng)用:大家在搶紅包,程序員在研究紅包算法》要點:
本文介紹了PHP應(yīng)用:大家在搶紅包,程序員在研究紅包算法,希望對您有用。如果有疑問,可以聯(lián)系我們。
大年節(jié)全天微信用戶紅包總發(fā)送量達到10.1億次,搖一搖互動量達到110億次,紅包峰值發(fā)送量為8.1億次/分鐘.PHP教程
拋開微信紅包的市場價值不談,紅包自己的算法也引發(fā)了熱議,由于官方?jīng)]有給出明確的說法,各家也是眾說紛紜,小編下面也為大家?guī)韼追N分析.PHP教程
首先看看數(shù)據(jù)闡發(fā)帝PHP教程
大多數(shù)人都做出本身的猜測,這也是在不知道內(nèi)部隨機算法的時候的唯一選擇,但是大多數(shù)人沒有給出本身親自的調(diào)查結(jié)果.這里給出一份100樣本的調(diào)查抽樣樣本數(shù)據(jù),并提出本身的猜測.
PHP教程
1. 錢包錢數(shù)滿足截尾正態(tài)隨機數(shù)分布.年夜致為在截尾正態(tài)分布中取隨機數(shù),并用其求和數(shù)除以總價值,獲得修正因子,再用修正因子乘上所有的隨機數(shù),得到紅包價值.PHP教程
這種分布意味著:低于平均值的紅包多,但是離平均值不遠;高于平均值的紅包少,但是遠年夜于平均值的紅包偏多.PHP教程
PHP教程
圖1. 錢包代價與其頻率分布直方圖及其正態(tài)擬合
PHP教程
但看分布直方圖并不克不及推出它符合正態(tài)分布,但是考慮到程序的簡潔性和隨機數(shù)的合理性,這是最合乎情理的一種猜測.
越是后面的錢包,價值普遍更高
PHP教程
PHP教程
圖2. 錢包序列數(shù)與其代價關(guān)系曲線PHP教程
從圖2中的線性擬合紅線可以看到,錢包價值的總體變化趨勢是在慢慢增大,其變化范圍大約是一個綠色虛線上下界劃出的“通道”.(曲線可以被圍在這么一個正合乎常規(guī)的“通道”中,也從側(cè)面反映了規(guī)律1的合理性,闡明了并不是均勻分布的隨機數(shù))
從另一個平均數(shù)的圖中也可以看出這一規(guī)律.
PHP教程
PHP教程
圖3. 平均數(shù)隨序列數(shù)的變化曲線PHP教程
在樣本中,1000價值的錢包被分成100份,均值為10.然而在圖3中我們可以看到在最后一個錢包之前,平均數(shù)一直低于10,這就闡明了一開始的錢包價值偏低,一直被后期的錢包價值拉著往上走,后期的錢包價值更高.PHP教程
3. 當然平均數(shù)的圖還可以透露出另一個規(guī)律,那就是最后的那一個人往往容易走運抽得比擬多.因為最后那一個人是錢包剩下多少就拿多少的,而之前所有人的平均數(shù) 都低于10,所以至少保證了最后一個人會高于平均值.在本樣本中,98號錢包抽到35,而最后一份錢包抽到46.PHP教程
綜上,根據(jù)樣本猜測:
PHP教程
PHP教程
1. 抽到的錢年夜多數(shù)時候跟別人一樣少,但一旦一多,就容易多很多.
2. 越是抽后面的錢包,錢越容易多.
3. 最后一個人往往容易撞年夜運.PHP教程
點評:這種明顯很實際有差別,小編每次不管什么時候搶都是幾毛錢.
PHP教程
第二位同學寫了一個簡單python 代碼
PHP教程
據(jù)察看,紅包分錢滿足以下幾點:PHP教程
1.不會有人拿不到錢
PHP教程
2.不會提前分完
PHP教程
3.錢的波動范圍很年夜
PHP教程
紅包在一開始創(chuàng)建的時候,分配方案就訂好了.搶紅包的時候,不過是挨個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.浮點數(shù)精度問題
PHP教程
2.界限值的處理PHP教程
第三位同學依照網(wǎng)上流傳的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("本輪發(fā)紅包中第"+(math.indexOf(Collections.max(math))+1)+"個人手氣最佳"); j++; }
第四位同學的這種算法看起來非常科學.
PHP教程
他認為:
PHP教程
1、每個人都要能夠領(lǐng)取到紅包;
PHP教程
2、每個人領(lǐng)取到的紅包金額總和=總金額;
PHP教程
3、每個人領(lǐng)取到的紅包金額不等,但也不能差的太離譜,不然就敗興味;
PHP教程
4、算法必定要簡單,不然對不起騰訊這個招牌;
PHP教程
正式編碼之前,先搭建一個遞進的模型來闡發(fā)規(guī)律
PHP教程
設(shè)定總金額為10元,有N個人隨機領(lǐng)取:
PHP教程
N=1
PHP教程
則紅包金額=X元;
PHP教程
N=2
PHP教程
為保證第二個紅包可以正常發(fā)出,第一個紅包金額=0.01至9.99之間的某個隨機數(shù)
PHP教程
第二個紅包=10-第一個紅包金額;
PHP教程
N=3
PHP教程
紅包1=0.01至0.98之間的某個隨機數(shù)
PHP教程
紅包2=0.01至(10-紅包1-0.01)的某個隨機數(shù)
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("本輪發(fā)紅包中第"+(math.indexOf(Collections.max(math))+1)+"個人手氣最佳"); j++; }
輸入一看,波動太年夜,這數(shù)據(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("本輪發(fā)紅包中第"+(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教程
小結(jié):
PHP教程
小編覺得這完全可以理解成一個紅包引發(fā)的血案,小編僅僅列舉了幾個,還有一些工程學的同學直接拋出了數(shù)學模型、離散函數(shù)等等,然則無論算法是簡單還是復雜,玩的開心就夠了.PHP教程
歡迎參與《PHP應(yīng)用:大家在搶紅包,程序員在研究紅包算法》討論,分享您的想法,維易PHP學院為您提供專業(yè)教程。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/8758.html