微信紅包的算法實現

來自:Small

鏈接:http://blog.cqcoder.com/微信紅包的算法實現探討/

突發奇想給校友微信羣發了紅包,我設定紅包總額爲10元,支持28個人隨機領取


於是一個有趣的結果出現了


A 領取了 0.26元
B 領取了 0.29元
C 領取了 0.02元
D 領取了 0.56元
E 領取了 0.64元
……


微信是採用什麼樣的算法做到的?簡單百度了下,目前尚未有官方的說明,僅僅在知乎裏有一個較爲熱門的討論《微信紅包的隨機算法是怎樣實現的?》,鏈接,https://www.zhihu.com/question/22625187不過他們討論的太過於深入,有掉坑之嫌。


我按照自己的邏輯嘗試了下,這個算法需要滿足以下幾點要求

1、每個人都要能夠領取到紅包;

2、每個人領取到的紅包金額總和=總金額;

3、每個人領取到的紅包金額不等,但也不能差的太離譜,不然就沒趣味;

4、算法一定要簡單,不然對不起騰訊這個招牌;


正式編碼之前,先搭建一個遞進的模型來分析規律


設定總金額爲10元,有N個人隨機領取:
N=1 
則紅包金額=X元; 

N=2 
爲保證第二個紅包可以正常發出,第一個紅包金額=0.01至9.99之間的某個隨機數 
第二個紅包=10-第一個紅包金額; 

N=3 
紅包1=0.01至0.98之間的某個隨機數 
紅包2=0.01至(10-紅包1-0.01)的某個隨機數 
紅包3=10-紅包1-紅包2 

……

至此,規律出現啦!開始編碼!

C++

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<time.h>
using namespace std;
int main()
{
    cout<<"\t\t搶紅包遊戲"<<endl;
    int total;
    double totalnum,Min=0.01;//最少能收到0.01元
    cout<<"輸入紅包總數和總金額"<<endl;
    scanf("%d%lf",&total,&totalnum);
    srand((unsigned)time(NULL));
    for(int i=1;i<total;++i)
    {
        double safe_total=(totalnum-(total-i)*Min);
        double num1=((rand()%(int(safe_total*100)-int(Min*100)))+int(Min*100))/100.0;
         totalnum-=num1;
        cout<<"第"<<i<<"個紅包:\t"<<num1<<"元\t"<<"餘額:\t"<<totalnum<<"元"<<endl;
    }
    cout<<"第"<<total<<"個紅包:\t"<<totalnum<<"元\t"<<"餘額:\t"<<"0元"<<endl;
}
輸入一看,波動太大,這數據太無趣了!

                搶紅包遊戲
輸入紅包總數和總金額
8 30
第1個紅包:      3.76元  餘額:   26.24元
第2個紅包:      21.59元 餘額:   4.65元
第3個紅包:      2.61元  餘額:   2.04元
第4個紅包:      1.96元  餘額:   0.08元
第5個紅包:      0.02元  餘額:   0.06元
第6個紅包:      0.02元  餘額:   0.04元
第7個紅包:      0.02元  餘額:   0.02元
第8個紅包:      0.02元  餘額:   0元

改良一下,將平均值作爲隨機安全上限來控制波動差

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<time.h>
using namespace std;
int main()
{
    cout<<"\t\t搶紅包遊戲"<<endl;
    int total;
    double totalnum,Min=0.01;//最少能收到0.01元
    cout<<"輸入紅包總數和總金額"<<endl;
    scanf("%d%lf",&total,&totalnum);
    srand((unsigned)time(NULL));
    for(int i=1;i<total;++i)
    {
        double safe_total=(totalnum-(total-i)*Min)/(total-i);
        double num1=((rand()%(int(safe_total*100)-int(Min*100)))+int(Min*100))/100.0;
         totalnum-=num1;
        cout<<"第"<<i<<"個紅包:\t"<<num1<<"元\t"<<"餘額:\t"<<totalnum<<"元"<<endl;
    }
    cout<<"第"<<total<<"個紅包:\t"<<totalnum<<"元\t"<<"餘額:\t"<<"0元"<<endl;
}
輸出結果見下圖

                搶紅包遊戲
輸入紅包總數和總金額
8 30
第1個紅包:      1.36元  餘額:   28.64元
第2個紅包:      0.86元  餘額:   27.78元
第3個紅包:      4.13元  餘額:   23.65元
第4個紅包:      4.93元  餘額:   18.72元
第5個紅包:      0.49元  餘額:   18.23元
第6個紅包:      8.85元  餘額:   9.38元
第7個紅包:      7.6元   餘額:   1.78元
第8個紅包:      1.78元  餘額:   0元




發佈了27 篇原創文章 · 獲贊 10 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章