700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 微信群红包模拟器-怎样抢最大的红包

微信群红包模拟器-怎样抢最大的红包

时间:2022-03-11 22:45:49

相关推荐

微信群红包模拟器-怎样抢最大的红包

文章目录

1.前言2.微信红包模拟器3.统计结果分析4.小结

1.前言

微信红包我们天天都在抢,既然是抢红包,我们当然希望是能抢到越多越好,最好是能成为运气王,睥睨群芳。那么怎么才能成为运气王,靠玄学还是靠技术?只要我们足够闲,手机足够多,发出大量的红包,最终能发现其中的统计规律,可以大胆的指出,次序与总人数成黄金分割比的那一位获得运气王的几率最大。

2.微信红包模拟器

当然如果知道了微信红包分配的算法,我们也可以自己写一个红包模拟器来分发红包,获得统计规律。恋猫大鲤鱼在他的博客中介绍了微信红包的随机分配策略。

每次抢红包直接随机,随机的范围是[1, 剩余红包金额均值的两倍],单位分

具体为什么采取这样的分配策略,怎样保证公平可参见原博,这里我关心的是如何实现。

这里以C++为例进行实现,代码如下:

//// main.cpp// RedBag//// Created by EngzSinger on /3/1.//#include <iostream>#include <vector>#include <algorithm>#include <stdlib.h>#include <time.h>#include <numeric>#include <fstream>#include <string>using std::cout;using std::cin;using std::vector;using std::endl;using std::accumulate;using std::ofstream;using std::string;/** 定义一个红包分配器类*/class RedBagDistributor{private:int totalNum; //总红包个数int leftNum; //剩下的红包个数int balance; //余额int totalMoney; //红包总金额int minRand; //红包随机的下限int maxRand; //红包随机的上限,随剩余红包个数和余额的值更新int _Get_Luck_Not_Last(); //最后一个人的金额不是随机得到,所以这里将最后一个人和其他人的分配进行分别实现int _Get_Luck_Last();void _Remove_Bag();//封装leftNum-- 的操作void _Set_Max_Rand();//封装更新maxRand 的操作public:RedBagDistributor() : totalNum(5),leftNum(5),balance(10000),totalMoney(10000),minRand(1),maxRand(4000) {srand((unsigned)time(NULL));}RedBagDistributor(int total_num,int total_money) :totalNum(total_num),leftNum(total_num),balance(total_money),totalMoney(total_money),minRand(1),maxRand(2*total_money/total_num) {srand((unsigned)time(NULL));}int GetLuck(); //抽取红包void ReSet(); // 重设模拟器,避免多次模拟过程中模拟器频繁构造析构带来的消耗};/** 定义全局函数*/ofstream &print(ofstream &os,vector<int> vec){for(auto &a:vec){os << a <<'\t';}os << endl;return os;}double average(vector<int> array){size_t num = array.size();int sum = accumulate(array.begin(),array.end(),0);//cout<<num<<'\t'<<sum;return double(sum)/double(num);}/** 主函数* 进行10000次抢红包模拟,* 红包个数为10,红包总额为100元即10000分* 红包结果写入文件"Record.txt"中*/int main(int argc, const char * argv[]) {// insert code here...int bag_num = 10;int bag_sum = 10000;int frequency = 10000;string filename = "Record.txt";ofstream fout(filename);RedBagDistributor bador(bag_num,bag_sum);vector<vector<int>> RedBagRecord;RedBagRecord.resize(bag_num);for(auto &a:RedBagRecord){a.resize(frequency);}for(int i=0;i<frequency;++i){for(int j=0;j<bag_num;++j){RedBagRecord[j][i]=bador.GetLuck();}bador.ReSet();}int tmp_counter = 0;for(auto &a:RedBagRecord){tmp_counter++;cout<<"No."<<tmp_counter<<":"<<endl;cout<<"Average = "<<average(a)<<endl;cout<<"Max = "<<*max_element(a.begin(),a.end())<<endl;cout<<endl;}for(auto i=0;i<frequency;++i){vector<int> tmp;for(auto j=0;j<bag_num;++j) tmp.push_back(RedBagRecord[j][i]);print(fout,tmp);}return 0;}/** 类内函数的实现*/void RedBagDistributor::_Remove_Bag(){leftNum--;}int RedBagDistributor::_Get_Luck_Not_Last(){auto get_value = (rand() % (maxRand-minRand+1))+minRand;balance -= get_value;_Remove_Bag();return get_value;}int RedBagDistributor::_Get_Luck_Last(){_Remove_Bag();return balance;}int RedBagDistributor::GetLuck(){//if(leftNum==0) //exception_Set_Max_Rand();if(leftNum==1)return _Get_Luck_Last();elsereturn _Get_Luck_Not_Last();}void RedBagDistributor::_Set_Max_Rand(){maxRand = 2*(balance/leftNum);}void RedBagDistributor::ReSet(){leftNum = totalNum;balance = totalMoney;_Set_Max_Rand();//srand((unsigned)time(NULL));//秒级时间,程序运行过程中没有变化}

3.统计结果分析

首先是程序在标准输出设备的输出信息,可以看到对于每一个参与抢红包的人,所能获得红包的期望都在总体平均值附近浮动,这也比较符合红包设计的初衷,尽量保证分配过程的公平。细心观察不难发现,其中第六位能获得红包的平均值为1015.24,在所有人中比较突出,我们选择的总人数为10人,黄金分割位正好是第六个,所以充分验证我们开篇的猜想! 当然不是,我差点都信了,这只是一个巧合,多运行几次结果就不是第六个的平均值最大了。

平均值大家都一样,而最大值就比较有意思了,可以发现越往后能获得的最大值越大。其实这也好理解,随机范围的最大值是剩余均值的两倍,假设前面的人抢到的数值足够小,那么越往后剩余均值越大,对应的随机范围最大值也越大。

No.1:Average = 991.353Max = 2000No.2:Average = 998.175Max = 2214No.3:Average = 1001.36Max = 2439No.4:Average = 1001.67Max = 2760No.5:Average = 997.317Max = 3067No.6:Average = 1015.24Max = 3240No.7:Average = 1007.83Max = 3771No.8:Average = 995.736Max = 4383No.9:Average = 988.318Max = 5148No.10:Average = 1003Max = 5956

前面只是看到了每一位最大值,结果具有随机性,为了能看到更广泛的分布,我们可以把输出到文件的内容在Excel中进行处理,将每个位置对应的所有红包进行排序,绘制不同位置的红包散点图,看每个位置能拿到红包中最大若干个值的比较。可以看到位置越往后,获得的红包值上限越大。

4.小结

不管排在那个位置,获得红包的期望都是总体均值,但是越往后能获得的最大值越大,换言之,越往后越刺激。按照红包分配策略,最后一个人能拿到的是倒数第二个人抢完后的余额,两个人的红包应该差不多,但是从图中可以看出第九个人与第十个是相比有一点略微的优势。是因为统计样本不够大,还是因为数学原理掌控了结果?本文实现的模拟器放弃了对最后一个红包的限制,导致最后一个人可能抢到0元,如何优雅的解决这个问题。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。