Python中如何实现微信发红包的算法?
比如 100 元红包 10 个人抢,以下算法:先随机生成 10 个数,之和等于红包金额,然后依次从这个列表随机取一个
,取了后移除,在随机取一个,这样算法是否合理,公平不呢
def hongbao(amount=5, count=3):
s = []
sum = 0
min = 0.01
max = float(amount) - count * 0.01
num = 0
for i in range(count-1):
num = round(random.uniform(0, float(amount) - sum), 2)
while num < min or num > max:
num = round(random.uniform(0, float(amount) - sum), 2)
sum += num
s.append(num)
s.append(round(float(amount) - sum, 2))
# return s
for i in range(count):
temp = random.choice(s)
print(“第{0}个人抢的红包是{1}”.format(i + 1, temp))
s.remove(temp)
hongbao(100, 10)
测试有问题,问题在哪里呢
Python中如何实现微信发红包的算法?
难读…
import random
def wechat_red_packet(total_amount, num_people):
"""
微信红包算法实现
:param total_amount: 红包总金额(单位:元)
:param num_people: 抢红包人数
:return: 每个人分到的金额列表(单位:元)
"""
if total_amount <= 0 or num_people <= 0:
raise ValueError("金额和人数必须大于0")
# 转换为分计算,避免浮点数精度问题
total_cents = int(total_amount * 100)
if total_cents < num_people:
raise ValueError("每人至少能分到0.01元")
# 生成n-1个分割点
points = sorted(random.sample(range(1, total_cents), num_people - 1))
# 计算每个区间的长度(即每个人分到的金额)
result = []
prev = 0
for point in points:
result.append((point - prev) / 100.0) # 转换回元
prev = point
result.append((total_cents - prev) / 100.0)
# 随机打乱顺序(微信红包金额是随机的)
random.shuffle(result)
return result
# 示例使用
if __name__ == "__main__":
# 发一个100元的红包给10个人
amounts = wechat_red_packet(100, 10)
print(f"红包分配结果:{amounts}")
print(f"总金额验证:{sum(amounts):.2f}元")
这个算法的核心是线段分割法:把总金额想象成一条线段,随机插入n-1个分割点,就能得到n个随机金额的线段。关键点有四个:1)用分而不是元计算避免浮点误差;2)保证每人至少0.01元;3)分割点不重复;4)最后打乱顺序让金额分布更随机。
实际微信的算法会更复杂些,加入了延迟计算和防作弊机制,但这个基础版本已经能满足大部分场景。
二倍均值法
我看了下那些 stackoverflow 的回复,
最简单的是生成 10 个随机数,然后按照比例来分 100 元
整理思路如下:
#算法一
#################################################################
def hongbao(amount=5, count=3):
s = []
min = 1 #分
amount = amount * 100 #单位分
max = amount - (count-1) #单位分
for i in range(count-1):
# num = random.randint(0, amount)
num = random.uniform(0, int(amount))
while num < min or num > max:
num = random.uniform(0, int(amount))
amount -= num
s.append(round((num / 100), 2))
s.append(round((amount / 100), 2))
random.shuffle(s)
return s
print(hongbao(1, 6))
##############################################################
算法二
#############################################################
# 0–|----|--------|-----------|-------20
# 0 2 4 10 16 20
def hongbao(amount=10, count=5):
ret = random.sample(range(1, amount * 100), count - 1) #分为单位
ret.extend([0, amount * 100]) #追加多个值 0 amount * 100
ret.sort() #排序
# return [((ret[i+1] - ret[i]) / 100 for i in range(num))] # 列表生产式
for i in range(count):
yield (ret[i+1] - ret[i]) / 100
res = hongbao(10, 6)
for i in res:
print(i)

