微信红包算法思考学习研究

闲来无事,研究下微信的红包算法,也思考下可以实现的其他算法,略作记录。

微信红包的随机算法不是在发红包时就算好的,而是用户在领取红包时实时计算出客户领取红包金额,因此红包的算法重点在于如何公平地算出领取人领取的红包金额。
可以转换为问题:从资金为S、个数为N的红包池中公平地随机取一个随机数,要求保证每个人都可以领取到红包。

总额随机法

算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时为保证每个客户有红包可领,先保留最小预留金额K=P=10,然后对其他部分直接取随机值R=rand()%(B-P)=rand()%90,最后取R+1作为本次随机领取的红包金额。
优缺点:算法不公平,未体现在平均值范围内波动,结果差异很大。
主要实现算法如下:

// 总额随机法
// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时
// 为保证每个客户有红包可领,先保留最小预留金额K=P=10,然后对其他部分直接取随机值
// R=rand()%(B-P)=rand()%90,最后取R+1作为本次随机领取的红包金额
// 优缺点:算法不公平,未体现在平均值范围内波动,结果差异很大
static size_t PickRand(size_t nBal, size_t nNum)
{size_t nPick = nBal - nNum;if (nNum != 1){nPick = (nPick ? rand() % nPick : 0) + 1;}else{nPick = nBal;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;
}

平均数加减法

算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,先取的平均数AVG=B/P=10,然后在平均数上再进行随机的加或减平均数以内的随机数RAVG=rand()/AVG,如此即可从红包池中获取一个随机金额的红包R=AVG+RAVG或R=AVG-RAVG。
注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B
优缺点:算法公平,在均值范围内波动

// 平均数加减法
// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,
// 先取的平均数AVG=B/P=10,然后在平均数上再进行随机的加或减平均数以内的随机数RAVG=rand()/AVG,
// 如此即可从红包池中获取一个随机金额的红包R=AVG+RAVG或R=AVG-RAVG
// 注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B
// 优缺点:算法公平,在均值范围内波动
static size_t PickAvgPM(size_t nBal, size_t nNum)
{// 先预定最小金额size_t nPick = 1;if(nNum != 1){// 总额减去基本数nBal -= nNum;// 随机金额:平均数±平均数内的随机值size_t nAvg = nBal / nNum;size_t nRand = (nAvg ? rand() % nAvg : 0);nAvg += (rand() % 2 ? nRand : 0 - nRand);nPick += nAvg;}else{nPick = nBal;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;
}

微信红包法

算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,先取的平均数AVG=B/P=10,据此计算出本次领取金额的范围为2AVG,即1至20,如此即可从红包池中获取一个随机金额的红包R=rand()%(2AVG)=1 + rand()%20。
注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B
优缺点:算法公平,在均值范围内波动

// 微信红包法
// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,
// 先取的平均数AVG=B/P=10,据此计算出本次领取金额的范围为2*AVG,即1至20,
// 如此即可从红包池中获取一个随机金额的红包R=rand()%(2*AVG)=1 + rand()%20
// 注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B
// 优缺点:算法公平,在均值范围内波动
static size_t PickAvgWx(size_t nBal, size_t nNum)
{size_t nPick = nBal;if (nNum != 1){// 平均数*2// 总金额-总人数是为了保证剩余的每个人都有红包可领size_t nAvg = (nBal-nNum)/nNum;nPick = (nAvg? rand()%nAvg:0) + 1;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;
}

测试代码

#include <iostream>
#include <string>
#include <assert.h>
#include <time.h>
#include <windows.h>using namespace std;
class CDivideRedPacket
{private:size_t  _nNum;       // 红包个数size_t  _nBal;       // 红包总金额,单位为分。取整型而不是浮点型提高性能string  _strRemark;  // 备注信息size_t  _nPicked;    // 已经领取的个数size_t  _nPickedBal; // 已经领取的金额public:// 构造析构函数CDivideRedPacket() { Reset(); }// 参数设置bool SetPara(size_t nNum, double fBal, string strRemark = "恭喜发财,大吉大利"){// 重置数据Reset();if (fBal <= 0){cout << "红包金额必须大于0" << endl;return false;}_nBal = static_cast<size_t>(fBal * 100);if (nNum == 0){cout << "红包个数必须大于0" << endl;return false;}if (nNum > _nBal){cout << "红包个数太多,金额不够,请调整" << endl;return false;}_nNum = nNum;_strRemark = strRemark;cout << "设置红包成功:人数[" << _nNum << "] 金额[" << _nBal / 100.0f << "] 备注[" << _strRemark << "]" << endl;return true;}// 领取红包bool Pick(){// 检查红包数if (_nNum == 0 || _nNum == _nPicked){assert(_nBal == _nPickedBal);cout << "你来晚了,红包已被领完"<< endl;return false;}// 分配红包_nPickedBal += PickAvgWx(_nBal - _nPickedBal, _nNum - _nPicked++);}private:void Reset(){_nBal = 0;_nNum = 0;_strRemark = "恭喜发财,大吉大利";_nPicked = 0;_nPickedBal = 0;}// 随机法// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时// 为保证每个客户有红包可领,先保留最小预留金额K=P=10,然后对其他部分直接取随机值// R=rand()%(B-P)=rand()%90,最后取R+1作为本次随机领取的红包金额// 优缺点:算法不公平,未体现在平均值范围内波动,结果差异很大static size_t PickRand(size_t nBal, size_t nNum){size_t nPick = nBal - nNum;if (nNum != 1){nPick = (nPick ? rand() % nPick : 0) + 1;}else{nPick = nBal;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;}// 平均数加减法// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,// 先取的平均数AVG=B/P=10,然后在平均数上再进行随机的加或减平均数以内的随机数RAVG=rand()/AVG,// 如此即可从红包池中获取一个随机金额的红包R=AVG+RAVG或R=AVG-RAVG// 注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B// 优缺点:算法公平,在均值范围内波动static size_t PickAvgPM(size_t nBal, size_t nNum){// 先预定最小金额size_t nPick = 1;if(nNum != 1){// 总额减去基本数nBal -= nNum;// 随机金额:平均数±平均数内的随机值size_t nAvg = nBal / nNum;size_t nRand = (nAvg ? rand() % nAvg : 0);nAvg += (rand() % 2 ? nRand : 0 - nRand);nPick += nAvg;}else{nPick = nBal;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;}// 微信红包法// 算法描述:假设当前红包池的金额为B=100,待领取人数为P=10,从中领取一个随机红包的算法时,// 先取的平均数AVG=B/P=10,据此计算出本次领取金额的范围为2*AVG,即1至20,// 如此即可从红包池中获取一个随机金额的红包R=rand()%(2*AVG)=1 + rand()%20// 注意,红包池内的P=1时,直接取随机红包金额为红包池的金额B,即R=B// 优缺点:算法公平,在均值范围内波动static size_t PickAvgWx(size_t nBal, size_t nNum){size_t nPick = nBal;if (nNum != 1){// 平均数*2// 总金额-总人数是为了保证剩余的每个人都有红包可领size_t nAvg = (nBal-nNum)/nNum;nPick = (nAvg? rand()%nAvg:0) + 1;}cout << "恭喜你,你领取的红包金额为:" << nPick / 100.0f << "元" << endl;return nPick;}
};int main()
{CDivideRedPacket rp;srand(time(NULL));int nNum = 0;double fBal = 0.0f;while (true){nNum = 1 + rand() % 20;fBal = (1 + rand() % 1000000) / 100.f;if (rp.SetPara(nNum, fBal)){while (rp.Pick());}cout << "-----END----" << endl;// 如果为了验证正确性,可注释掉该暂停时间,查看程序运行是否异常Sleep(3000);}return 0;
}

执行结果示例

设置红包成功:人数[4] 金额[175.05] 备注[恭喜发财,大吉大利]
恭喜你,你领取的红包金额为:36.35元
恭喜你,你领取的红包金额为:38.87元
恭喜你,你领取的红包金额为:26.84元
恭喜你,你领取的红包金额为:72.99元
你来晚了,红包已被领完
-----END----
设置红包成功:人数[6] 金额[237.17] 备注[恭喜发财,大吉大利]
恭喜你,你领取的红包金额为:10.41元
恭喜你,你领取的红包金额为:28.64元
恭喜你,你领取的红包金额为:41.67元
恭喜你,你领取的红包金额为:9.61元
恭喜你,你领取的红包金额为:55.63元
恭喜你,你领取的红包金额为:91.21元
你来晚了,红包已被领完
-----END----
设置红包成功:人数[8] 金额[264.63] 备注[恭喜发财,大吉大利]
恭喜你,你领取的红包金额为:9.36元
恭喜你,你领取的红包金额为:14.42元
恭喜你,你领取的红包金额为:14.78元
恭喜你,你领取的红包金额为:37.58元
恭喜你,你领取的红包金额为:4.21元
恭喜你,你领取的红包金额为:20.68元
恭喜你,你领取的红包金额为:54.21元
恭喜你,你领取的红包金额为:109.39元
你来晚了,红包已被领完
-----END----

微信红包算法代码实现相关推荐

  1. matlab 发微信,微信红包算法MATLAB实现

    上午看到基友分享的微信红包算法的文章,代码很短,春节期间红包太火了,看完就也想实现下玩玩,原代码是JAVA的,没接触过JAVA,所以看懂后改成了MATLAB的.原文链接:微信红包随机算法初探 , 作者 ...

  2. matlab程序模拟微信抢红包,微信红包算法MATLAB实现

    上午看到基友分享的微信红包算法的文章,代码很短,春节期间红包太火了,看完就也想实现下玩玩,原代码是JAVA的,没接触过JAVA,所以看懂后改成了MATLAB的.原文链接:微信红包随机算法初探 , 作者 ...

  3. 一不小心错过的几个亿还可以再回来!解密微信红包算法

    前言 ◆ ◆ ◆ ◆ 还记得2017年,微信红包收发总量达到460亿个,2019年,除夕到初五,8.23亿人收发微信红包.一觉醒来,微信群里各种红包,顿时觉得错过了几个亿,破解了红包的规律,是不是就可 ...

  4. js 实现微信红包算法

    微信红包算法 5块钱生成五个红包,要注意的有 1.生成5个随机数 2.5个随机数加起来必须等于5 3.红包要设置最小值 如最小值不能小于0.01 4.红包要设置最大值,如果第一个红包为5,剩下四个红包 ...

  5. 微信抢红包代码 python_用 Python 实现一个简单的微信红包算法

    今年过年各位一定在微信里抢了不少红包.那么当别人是手气王而你只抢到1分钱的时候,你有没有想过,如果你来实现红包的分配算法,会怎么写? 这里我给一个简单的实现方案. 基本思路就是,有多少个红包,就循环多 ...

  6. js微信抢红包脚本代码_微信红包算法(js)

    下面实现一个微信红包的抽奖模拟,听说是微信的官方算法,我不确定,先看下实现思路(源码在文章最后): 设置最小金额为0.01,最大金额为剩余金额/剩余红包数量的2倍 在最大最小金额之间取一个随机数作为红 ...

  7. Python微信红包算法

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  8. 说说微信红包算法,为什么你总是抢的那么少?

    红包业务流程 拆包算法 1.无脑随机发  每个人抢红包,红包金额 = [0.01,红包剩余金额):最后一个人就不用随机了,无论剩下多少都是最后一个人的了. 2.线性切割法 把总金额数值,想象成一条绳子 ...

  9. autojs微信红包助手代码,供大家参考

    // vx版本8.0.23(其他版本也可尝试),测试手机为红米note10 pro,autojsPro版本8.8.22-common // 本代码只用于学习交流,严禁用于违法违规途径,后果自负 //前 ...

最新文章

  1. 附带数据库的应用程序
  2. Mysql小练习(1)
  3. 如何搭建SVN的服务器
  4. 如何维持手机电池寿命_充电小知识:你知道如何正确充电吗?这几种充电方式最损害电池...
  5. 基于Spring Security的认证方式_创建工程_Spring Security OAuth2.0认证授权---springcloud工作笔记119
  6. 实验4-1-8 求给定精度的简单交错序列部分和 (15 分)
  7. Hive map side join入门及测试
  8. ubuntu安装python库_ubuntu下的python请求库的安装
  9. java中关于日期类Calendar的简单使用
  10. 17个机器学习的常用算法!
  11. 9.屏幕宽高比判断(Screen.width,Screen.height)
  12. SM干货篇:你应该具备的提问技巧!
  13. 当“大数据”落地,当技术接轨商业
  14. 2020华为春招面试:一面二面三面(一下午4h左右完成)已挂
  15. BOM中的location对象
  16. Python绘制对多角星
  17. 【转】本人常用资源整理
  18. 大成都范围广告位招商
  19. 17网里多个商品里全部图片复制并分类保存的技巧
  20. n皇后问题-回溯法求解

热门文章

  1. 关于魅族note无法连接mac调试(转)
  2. Excel应该这么玩——7、我是预言家:绘制趋势图
  3. 完美日记、花西子竞品分析报告
  4. 2021年秋招算法岗面经-无人驾驶领域\slam\点云方向-百度\字节\旷视\商汤\文远知行\美团\高德\地平线\华为
  5. 计算机相关配置基本信息,教你怎么查看电脑配置基本信息
  6. RS232、RS422、RS485自环测试
  7. python2 urllib模块_python urllib与urllib2模块用法教程
  8. Shell sed命令
  9. JavaScript/JS获取屏幕的分辨率
  10. 我的电子游戏之旅--街霸与侍魂