前言
仅个人笔记,欢迎交流指正
概念
红包主要有三点限制
- 抢到的总额 = 红包的总额,不能多也不能少了
- 最小值是0.01元,即每个人都有份
- 每个人抢到的红包金额,尽量平均
实现逻辑
-
假设总金额是M元,N个人,每次抢的金额=(0, (M/N) *2) -
比如,金额100,人数10,第一个人抢的金额是 (0,20),抢到的数值,根据正态分布,应该是10左右,远低于10的概率很小,同样远大于10的概率和很小,这里假设第一个人抢到的数值是10; -
第二个人抢的金额是(0,90/9*2)=(0,20),同第一个人,第二个人红包金额也应该是10附近;剩下的人,以此类推。
提醒 参考的文章说这个算法不是完美的,假如第一个人抢到15,第二个人的范围是(0,18.89),假如第二个人又抢到很高,那对后面的人是不利的
代码实现
package main
import (
"errors"
"math/rand"
)
//RED_PACKET_MIN_MONEY 红包最小金额(单位:分)
const RED_PACKET_MIN_MONEY = 1
//RedPacketModel 红包信息实体
type RedPacketModel struct {
count int64 //红包个数
money int64 //红包金额(单位:分)
remainCount int64 //剩余红包个数
remainMoney int64 //剩余红包金额(单位:分)
bestLuckMoney int64 //手气最佳金额(单位:分)
bestLuckIndex int64 //手气最佳索引位置
historyRewards []int64 //历史红包记录
}
/*
CreateRedPacket
@Desc 生成红包
@Param count int64 红包个数
@Param money int64 红包金额
*/
func CreateRedPacket(count, money int64) (res *RedPacketModel, err error) {
if count <= 0 || money <= 0 || money < count*RED_PACKET_MIN_MONEY {
err = errors.New("parameter error")
return
}
res = &RedPacketModel{
count: count,
money: money,
remainCount: count,
remainMoney: money,
bestLuckMoney: 0,
bestLuckIndex: 0,
historyRewards: nil,
}
return
}
/*
Open
@Desc 拆红包(二倍均值法)
@Return money int64 本地拆红包获得金额
@Return res bool 拆红包失败,红包已经被抢光
*/
func (r *RedPacketModel) Open() (money int64, res bool) {
//检测红包是否被抢光
if r.Check() {
return
}
//最后一个红包
if r.remainCount == 1 {
money = r.remainMoney
} else {
//最大可用金额 = 剩余红包金额 - 后续多少个没拆的包所需要的保底金额
//目的是为了保证后续的包至少都能分到最低保底金额,避免后续未拆的红包出现金额0
maxCanUseMoney := r.remainMoney - RED_PACKET_MIN_MONEY*r.remainCount
//2倍均值基础金额
maxAvg := maxCanUseMoney / r.remainCount
//2倍均值范围数额
maxMoney := maxAvg*2 + RED_PACKET_MIN_MONEY
//随机红包数额
money = rand.Int63n(maxMoney) + RED_PACKET_MIN_MONEY
}
//手气最佳
if money > r.bestLuckMoney {
r.bestLuckMoney = money
r.bestLuckIndex = r.count - r.remainCount
}
res = true
r.remainMoney -= money
r.remainCount--
r.historyRewards = append(r.historyRewards, money)
return
}
/*
Check
@Desc 校验红包是否被抢完
*/
func (r *RedPacketModel) Check() bool {
return r.remainCount == 0
}
参考
- 参考:https://www.yisu.com/zixun/310871.html
|