关于微信手气红包算法的探讨
前言
这大过年的,长辈家人朋友发的红包抢到手软,嘿嘿嘿。昨晚,和一个朋友出去浪,刚好两人现在就读专业相同,不知不觉间就谈到了微信红包的算法。今天闲来无事,就简单的做了一下记录。
第一种
这个是最简单的实现,就是先给每个红包分配0.01(确保大家都有),然后各个红包轮流产生一个随机数(不得大于当前总金额)并从总金额中取出相应的数,最后一个红包不管如何,全盘接收总金额。
贴 java 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ```java /** * 最简单的分配方法,单位全部统一为 分 * @param number 红包总数 * @param money 金额总数 */ public void redPacket1 ( int number, int money){ int minCount = 1 ; //最低金额 int moneyCount = money* 100 - minCount*number; //分配给各个红包 0.01后可分配金额 Random random = new Random(); float [] array = new float [number]; //储存红包金额的数组 StringBuffer arrayStr = new StringBuffer( "" ); //为了方便显示 //为前 number-1 个红包分配金额 for ( int i= 0 ; i<number- 1 ; i++){ try { array[i] = (minCount+random.nextInt(moneyCount)) ; } catch (IllegalArgumentException e){ //防止 moneyCount 为0 array[i] = minCount ; } if (moneyCount!= 0 ) //可分配金额可以继续分配 moneyCount -= array[i]; arrayStr.append(String.valueOf(( double ) array[i]/ 100 ) + " " ); } array[number- 1 ] = moneyCount+minCount; arrayStr.append(String.valueOf(( double ) array[number- 1 ]/ 100 ) + " " ); System.out.println(arrayStr); //将各个红包金额打印出来 } |
测试贴图:
假设有个20块的手气红包,分配为10个,(不考虑边界数据的情况)
从结果中可以很清楚看出它的缺陷:
* 波动太大;
* 先抢的人往往会占据大部分红包。
不过,我觉得这种算法还是存在的,一般适应于大红包少人的情况:
我怀疑我抢了个假红包!!!
第二种
第二种主要就是给随机数增加一个上限,我朋友说可以使用总金额平均数来控制波动,我觉得可以改为使用平均数的某个倍数(我限制为1.0-2.9之间波动)。毕竟,抢红包体现出欧皇气质也不失为一种极大的乐趣!
同时,因为 java 中的 Random() 是一个伪随机数,为了防止倍数与金额随机数的影响(程序猿癖好),我重新 new 了个对象和封装为方法使用。
贴 java 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * 分配方法二,单位全部统一为 分 * @param number 红包总数 * @param money 金额总数 */ public void redPacket2( int number, int money){ Random random = new Random(); float times = ( float )random.nextInt( 20 )/ 10 + 1 ; //获取一个倍数 StringBuffer buffer = new StringBuffer(); int minCount = 1 ; int moneyCount = money * 100 ; //这次是金额总数 int max = ( int )(moneyCount*times/number); //可分配最大值 for ( int i= 0 ; i<number; i++){ int packet = randomPacket(minCount, max, number-i, moneyCount); moneyCount -= packet; buffer.append(String.valueOf(( double ) packet/ 100 ) + " " ); } buffer.append( " 倍数为:" +times); System.out.println(buffer); } |
封装的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * 分配一个红包 * @param minCount * @param maxCount * @param number * @param money * @return */ private int randomPacket( int minCount, int maxCount, int number, int money){ Random random = new Random(); if (number == 1 ) return money; //最后一个红包 if (minCount == maxCount) return minCount; //最大随机数与最小随机数相同 int max = maxCount>money ? money : maxCount; //若倍数最大值大于现在的金额时,动态改变波动上限 int packet = minCount; try { packet += random.nextInt(max-minCount); } catch (IllegalArgumentException e){ //还是可能出现 max-minCount 为 0 的情况 packet += 0 ; } return packet; } |
测试贴图:
假设有个20块的手气红包,分配为10个,(不考虑边界数据的情况)
这次许多数值就比较正常,但还是有缺陷的,我觉得微信红包出现 0.01 的概率比较大,但这种算法得出 0.01 的概率不是一般的小。Ps:100次测试中出现只出现了一次0.01。
最后
我自己觉得微信抢红包的算法肯定不止一种,应该是在某个金额和红包数时选择某种更具趣味性的算法。知乎上也有一个关于红包算法的讨论,也有许多可取之处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具