问题描述
- 使用 python 实现类似微信发红包的功能,尽量保持每个人收获的红包平均,要求输入总金额 money(元-float)及红包个数 num(个-int),且每人最小获得的红包额度不能小于0.01元(不考虑 money/num < 0.01此种输入情况,如money=0.1,int=100,平均每个人0.001元,输入非法)
- 返回一个列表,长度为num,包含了每个红包的额度,顺序随机,且列表中数字总和为money
思路分析
- 难点在于如何确定红包的随机性和每个红包的总和恰好等于总金额
- 如果我们在输入的money长度的坐标轴上随机取 num-1个点,那么这些点之间的间距肯定是随机的,当左侧添加上0点,右侧添加上money点,那么每一段线段的长度和恰好等于money的长度。
如下图所示:
这样的思路可以保证数据的随机性,和总金额的准确 - Tips:随机取0-money范围的数值直接作为红包的面额,易于造成分配严重不均,导致剩余的其它红包不够分的问题。如果使用二分法,只取剩余总额度的一半的取值,又不能满足随机性,因为这样的方法先抢的人得到较大额度的概率更大。
代码实现
import randomdef redbags(money, num):# 使用random.sample()可以得到1分-money*100分以内的 num-1个随机值valueList = random.sample(range(1, int(money * 100)), num - 1)# 加入 0 和 money*100 两个值,此时valueList的长度使 num+1valueList.extend([0, money * 100])# 排序valueList.sort()res = []for i in range(num): # 因为只需要num个数值,所以循环num次cost = valueList[i + 1] - valueList[i] # 两个随机数之间的长度res.append(cost)res2 = [str(i / 100.0) for i in res] # 除以100.0 是为了精度精确到分return res2if __name__ == '__main__':total = float(input("请输入红包总金额(回车继续):"))num = input("请输入红包个数(回车结束):")if num.isdigit():print("红包配额为:%s" % (",".join(redbags(total, int(num)))))else:print("Error:输入红包个数必需为整数")
输入: money=100, num=10
输出:
如有错误,欢迎指正!
参考自:
https://www.jb51.net/article/169096.htm