微信演算法筆試
㈠ 微信紅包的隨機演算法是怎樣實現的
下面是一個比較拙的演算法,真實的紅包隨機數要稍微復雜些:
classProgram
{
staticvoidMain(string[]args)
{
double[]hb=WeiXin.Hongbao(5,1);
for(inti=0;i<5;i++)
{
Console.WriteLine(hb[i]);
}
}
}
///<summary>
///微信類
///</summary>
publicclassWeiXin
{
///<summary>
///紅包隨機分配
///</summary>
///<paramname="personNumber">紅包個數</param>
///<paramname="money">金額</param>
///<returns></returns>
publicstaticdouble[]Hongbao(intpersonNumber,doublemoney)
{
Randomrand=newRandom();
doublefen=money;
double[]hb=newdouble[personNumber];
doublerm=0D;
//預分配
for(inti=0;i<personNumber;i++)hb[i]=0.01;
fen-=(personNumber*0.01);
if(fen>0.01)
{
//隨機分配
while(fen>0)
{
rm=GetRandomNumber(0.01,fen);
hb[rand.Next(0,personNumber)]+=rm;
fen-=rm;
}
}
returnhb;
}
///<summary>
///返回介於minimum和maximum之間的隨機數
///</summary>
///<paramname="minimum">最小值</param>
///<paramname="maximum">最大值</param>
///<returns></returns>
(doubleminimum,doublemaximum)
{
Randomrandom=newRandom();
returnMath.Round(random.NextDouble()*(maximum-minimum)+minimum,2);
}
}
㈡ 微信紅包的隨機演算法是怎樣的
1)紅包大小服從截尾正態分布,其好處是減少抽取紅包大小分布的方差,讓更多的人抽取的紅包在均值附近,同時仍給一小部分人抽取大紅包的機會,總體來說增加了紅包抽取人的積極性和游戲的公平性;
2)抽取紅包大小與抽取紅包先後無相關性。一種可能的紅包產生機制是:當發紅包者<准備紅包>的時候,程序自動依照截尾分布產生了相應大小,相應個數的紅包,然後隨機發給抽取紅包的人。同樣,這樣的一個隨機過程有助於增加游戲的公平性,也減少了紅包抽取人投機操作。
錢包錢數滿足截尾正態隨機數分布。大致為在截尾正態分布中取隨機數,並用其求和數除以總價值,獲得修正因子,再用修正因子乘上所有的隨機數,得到紅包價值。
這種分布意味著:低於平均值的紅包多,但是離平均值不遠;高於平均值的紅包少,但是遠大於平均值的紅包
㈢ 微信紅包的隨機演算法是怎樣實現的
我們在一個20人的群中,自己發紅包以及結合其他人發出紅包的情況,整合成兩輪的數據。每次金額設置都是20塊並且有20個,第一輪是發了15次,第二輪是發了19次,總結成表格,然後為了避免突發的數據影響判斷,我們將兩輪數據雜糅從而生成了其他的三輪數據,一共是五輪數據。羅列如下表,高亮的數據為最佳手氣。每一列的數據最早搶到紅包的在最底端,越往上越晚搶。
從所有黃色的數值(最佳手氣金額)可看出,所有最佳手氣值都在平均值*2的前後附近(平均值=總金額/紅包總個數,這里平均值=20/20=1),事實上確實如此,可通過微信紅包分發演算法得到驗證,演算法具體見後文
然後我們選取部分數據開始製作散點圖。橫軸為1-20,分別表示搶到紅包的人的編號,隨遞增而越早。也就是20代表最早搶到的人。縱軸為金額。同樣的形狀顏色的點代表一次發紅包,然後我們抓取部分數據顯示為散點圖,越密集代表該順序位的用戶得到的金額越穩定。散點圖如下:
規律一:我們可以看到,所有紅包大多數金額分布在0.5到1.5元之間,顯示為圖中方框所示,大部分點都分布在這個位置。然後是順序位密集程度的對比,可以發現20、19,也就是最先搶到紅包的人,小圓圈所示基本的點都集中在小范圍,說明先搶紅包的人得到的金額會比較穩定,但同時最佳手氣的概率也比較低。大圓圈所示的是極不穩定,飄忽的金額分布,表示越晚搶紅包得到的金額會飄忽不穩,但同時,搶到最佳手氣等大金額的紅包概率也比早搶的高。
根據上面的分析,我們又寫了一個過濾計數函數,針對金額的分段的紅包個數進行統計:
比如2.0-2.5
得到如下金額分布:
折線圖:
規律二:絕大多數的紅包的金額都集中在1-1.5,也就是說20塊錢發20個紅包的金額分布集中在比平均數大一點點的附近,同時較大幅超過平均數金額的紅包大大少於低於於平均數的紅包數量。
那我們繼續擴大數據的規模,將幾輪數據的均值和標准差分別做成折線圖:
綜合上面各個折線圖的情況,我們可以得到越早搶紅包的標准差越小,越晚搶紅包的標准差越大,但同時,由均值和總額可以看出來,越早搶紅包的均值往往要更高,紅包金額得到最佳手氣概率也會相對較小,越晚搶紅包的人則得到最佳手氣等大手氣的概率更大。
為了得到更為趨近規律的曲線和規律,我們決定將兩輪真實數據合並起來,然後給出冪函數的趨近線(虛線),如下圖:
由於均值受極值波動影響較大,所以我們去除一些因為偶然差產生的極端點(圓圈的點)從而發現是遞增的趨勢。
規律三:可以很明顯的看到,均值是隨著搶紅包的越晚而緩慢遞減,標准差值同時也往上遞增,這個趨勢結合之前的分析,我們猜想,即標准差越大說明,領取到最大的紅包和最小紅包的風險越大,也就是說越晚搶標准差越大,對於冒險主義者來講是最好的,因為他有很大概率獲得最大的金額,但也大概率獲得最小的紅包,風險與收益並存;均值越大,說明每次都拿到一個不大不小的紅包,雖然獲得最小和最大金額紅包的概率很小,但起碼不虧本,也就是說越早搶,均值越穩定,這比較適合不喜歡冒險的人。
驗證預測結果:
21:24分發送預測結果到另一位同學微信:
隨後開始發紅包:
結果:
最佳手氣為第8個人且金額為1.13
與預測結果一致,規律基本正確!
總結:
(1)最佳手氣為1.13塊,根據我們推導的預測公式=總額/紅包總個數*2*隨機數(0-2的double數), 也就是說最佳手氣在總額/紅包總個數*2值的前後附近。這里我們判斷在0.8-1.3之間,推斷正確
(2)平均值為0.5元,0.5-0.8元的紅包有3個,小於0.5的紅包有6個,說明大於平均值的紅包個數多於小於平均值的個數。與我們的第二點預測完全正確
(3)最佳手氣位置:根據我們的散點圖發現,最先搶到紅包的人,得到的金額會比較穩定,但同時最佳手氣的概率也比較低。表示越晚搶紅包得到的金額波動較大,但同時搶到最佳手氣等大金額的紅包概率也比早搶的高。所以我們推斷,最佳手氣位置在最後20%-30%之間。
微信紅包隨機分發演算法c++模擬:
基本思路:每次搶到一個紅包金額等於:紅包剩餘金額/紅包剩餘個數*2*隨機數(0-1的double型),如果計算的結果小於等於0.01,則取0.01值
主要代碼:
double packages[50000];
double Luckiest_money=0;
void getPackage(int remainSize,double remainMoney){
srand((unsigned)time(NULL));
for(int i=0;i