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

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

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

相关推荐
Asthenia041233 分钟前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom1 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide1 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04123 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫