策略模式实现红包分配算法

桃李春风一杯酒,江湖夜雨十年灯。

1 前言

在前文中已经分享了模板和策略模式的实践SpringBoot-策略和模板模式的思考与实践,在本文中将结合红包算法的场景再次进行实践,主要还是分享红包计算的思考逻辑和心得。在前文中已经介绍了订单拆分的算法,红包的算法和订单的算法有相似的地方。

2 业务分析

对于红包,大家能想到的一定是抢红包的场景,因为这个是一个并发场景且是领取红包的场景,考察的知识点比较多,但是这里介绍的红包业务是需要全面覆盖的,需要从发红包开始,至于红包的领取,会在后续的文章来分享。红包的类型可以分为个人红包和群红包(群红包可以分为平分模式和拼手气模式),在本文中将着重介绍拼手气红包的分配算法。

对于平分模式的红包比较简单,采用算术评分是即可,在 java 中会出现除不尽的情况即尾差的问题,则需要使用减法来处理最后一个数据。

对于拼手气模式的红包,相对来说比较复杂一点,既要保证红包分配的均匀性,也要考虑到红包之间的差异,还有一个红包最小金额的问题。假设需要发 n 个红包,在计算第 i 个红包的随机金额时,随机数的范围最小值即红包的最小金额,最大金额的设置要保证至少有 (n - i) 个红包最小金额。即便是如此,也不能保证一次循环就可以得到所有的红包金额,所以还需要设置本次要分的最大金额要小于未分配金额的 m 倍,这样才可以保证一次循环分配所有的红包金额。

css 复制代码
# 假设需要分配 n 个红包红包分配总金额为 m ,红包分配的最小金额为 0.1 ,则每次分配的最小金额为 0.01
第i次要分配的红包金额随机数取数范围为
amt = [0.01,(m -p - 0.01*(n-i)) * 0.66]
p 为第 i 次已经分配的红包总金额
如果本次分配最大金额为剩余待分配金额的 k 倍,则系数为 k/(k +1 ), 0.66 即表示2倍,倍数越大,红包的极值差越大,否则就越小

3 红包算法

红包平分模式的算法比较简单,需要按照比例来计算每个红包的金额,在 java 编程中但凡涉及到除法,都会存在除不尽的情况,所以最后一个一定要使用减法,才能保证子单和主单的金额一致性

3.1 红包平分算法

红包平均算法就是使用算术平均方法,在 java 中对于四则运算中的除法需要考虑结果的保留位数,否则遇到除不尽的情况会报 Invalid rounding mode 的错误。最后一个红包需要使用减法来计算,否则单个红包的累计之和红包总金额不一致。在操作计算时,可以使用 hutools 中的 Numutils 工具类进行计算,可以很方便的实现计算。

3.2 拼手气算法

红包拼手气的算法如下图所示,核心的逻辑还是计算每个红包的具体金额,保证每个红包的差异性,也要保证红包间的均衡性。这里使用的是 N 倍余额算法。在计算过程中可以使用 Numutils 工具类实现便捷计算。

7 总结

在本文中,主要介绍了发红包的类型和红包算法的实现,在后续文章中将使用策略模式来实现红包的发放和领取,通过红包的业务增强了对订单金额计算深刻的认知,也拓展巩固了作者的业务理解,同时也对设计模式有了新的感悟和心得。项目 github 地址 springboot-auth

相关推荐
C++ 老炮儿的技术栈1 小时前
UDP 与 TCP 的区别是什么?
开发语言·c++·windows·算法·visual studio
殇者知忧1 小时前
【论文笔记】若干矿井粉尘检测算法概述
深度学习·神经网络·算法·随机森林·机器学习·支持向量机·计算机视觉
mochensage3 小时前
C++信息学竞赛中常用函数的一般用法
java·c++·算法
烛阴3 小时前
bignumber.js深度解析:驾驭任意精度计算的终极武器
前端·javascript·后端
chengooooooo3 小时前
leetcode Top100 238. 除自身以外数组的乘积|数组系列
算法·leetcode
GUIQU.3 小时前
【每日一题 | 2025年6.2 ~ 6.8】第16届蓝桥杯部分偏简单题
算法·蓝桥杯·每日一题
服务端技术栈3 小时前
电商营销系统中的幂等性设计:从抽奖积分发放谈起
后端
你的人类朋友3 小时前
✍️Node.js CMS框架概述:Directus与Strapi详解
javascript·后端·node.js
面朝大海,春不暖,花不开4 小时前
自定义Spring Boot Starter的全面指南
java·spring boot·后端
weixin_527550404 小时前
初级程序员入门指南
javascript·python·算法