抢红包算法详解来源于【程序员小灰】的文章:https://mp.weixin.qq.com/s/AIE33sdT2QI6UL8cs1kJCQ
以下为python简单实现:
import random
from decimal import Decimal
def qhb(money: float, num: int) -> list:
"""抢红包算法 - 线段切割法。传入参数:红包金额(单位:元)money、红包个数num"""
if num <= 0:
return None
# 由单位元转为分,减少浮点数带来的影响
v_money = int(money * 100)
# 只有一个红包,直接返回红包总额
if num == 1:
return [v_money]
# 从【1,v_money-1】取随机整数作为线段切割点。若该整数不在列表当中,插入该整数,直到获取够num-1的切割点
hb_split_list = []
while len(hb_split_list) < num - 1:
single_hb = random.randint(1, v_money - 1)
if single_hb not in hb_split_list:
hb_split_list.append(single_hb)
# 对切割点升序排序,遍历列表时用当前切割点的值减上一个切割点的值
# 第一个切割点与0相减
# 这样得到num-1个红包金额
hb_split_list.sort()
hb_list = []
last_value = 0
for split_line_value in hb_split_list:
# 这个时候要把【分】换算回【元】,借助Decimal保证精度准确性
hb_list.append(Decimal(split_line_value - last_value) / 100)
last_value = split_line_value
# 第num个红包通过v_money与最后一个切割点相减得到,这个时候也要把【分】换算回【元】
hb_list.append(Decimal(v_money - last_value) / 100)
return hb_list
if __name__ == "__main__":
v = qhb(1000.10, 100)
print(v)
# 验算
v_sum = Decimal("0")
for vv in v:
v_sum = v_sum + vv
print(v_sum)