鱼C论坛

 找回密码
 立即注册
查看: 2249|回复: 3

[已解决]random模拟微信发红包

[复制链接]
发表于 2021-6-6 14:45:04 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
import random
def hongbao(total,num):
    each=[]
    already=0
    for i in range(1,num):
        t=random.randint(1,(total-already)-(num-i))
        each.append(t)
        already=already+t
    each.append(total-already)
    return each
if __name__=='__main__':
    total=300
    num=5
    for i in range(10):
        each=hongbao(total,num)
        print(each)


哪个大神能帮忙详细解释一下这个程序,促进一下理解
能看懂但是自己写就不会了
最佳答案
2021-6-7 16:29:55
本帖最后由 qq1151985918 于 2021-6-7 16:40 编辑
# 首先要看懂整片代码的意义,得一句一句代码分析
# 并且揣摩写代码人的用意
# 这个代码是有比较明显缺陷的
# 缺陷就是 越是前边领取红包的人领取的金额越大
# 越是后边领取红包的人领取的金额越小
# 代码案例中 取 num = 5 就已经很明显了
# 预计代码如果取 num = 20 就没法看了

# 加载模块
import random

# 定义函数 total 为红包总金额 num 为红包个数
def hongbao(total,num):
    
    # each 这里的作用就是储存已经领取的红包金额和人数
    # 如果第一个人领取了 1 块钱,each 就变成 [1]
    # 如果第二个人领取了 2 块钱,each 就变成 [1, 2]
    each=[]
    
    # already 这里的作用是计算已经领取的红包金额
    # 如果第一个人领取了 1 块钱,already 就变成 1
    # 如果第二个人领取了 2 块钱,already 就变成 3
    # total-already 表示剩余未被领取的金额
    already=0

    # 这里用的 range(1,num) 其实是有深意的
    # 故意少算了一个红包,因为用这个代码
    # 无法保证最后一个人拿到全部的剩余金额
    # 所以在最后又单独加了一个 each.append(total-already)
    # 将全部剩余金额都分配给最后领取的人
    for i in range(1,num):

        # 我们知道 randint 的取值是比较特殊的
        # 一般我们认知的取值区间都是 左闭右开
        # 但是 randint 的取值是 全闭区间
        # 这也是为什么在上面说的要把红包分配少一个人的原因之一
        # 也是下边代码 最后 -(num-i) 的原因
        # 写代码的人的想法是,要保证领取红包的人最少能够领取 1 元
        # 不知道你能不能看懂
        # 全部代码最有深度的就是下边的这一行代码
        # 一定要把这一行代码吃透
        # 这一行代码保证了每个领取到红包的人最少领取到 1 块钱
        # total-already 表示剩余未领取的钱
        # range(1,num) 是取不到 num 的值的,只能取到 num - 1
        # 如果确实看不懂再问吧
        t=random.randint(1,(total-already)-(num-i))

        # 将已经领取的红包储存
        each.append(t)

        # 更新已经领取的金额 already
        already=already+t

    # 将最后剩余金额全部分配给最后一个领取到红包的人
    each.append(total-already)
    
    # 将红包信息返回
    return each
if __name__=='__main__':
    total=300
    num=5

    # 模拟 10 次红包 均为 300 元 5 人
    for i in range(10):
        each=hongbao(total,num)
        print(each)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-6-6 19:31:32 | 显示全部楼层
pycharm开debug自己看过程就行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-7 09:57:35 | 显示全部楼层
本帖最后由 阿奇_o 于 2021-6-7 11:24 编辑

"能看懂",但“自己写就不会” ?——那你到底是看没看懂呀。。

建议可以自己先写写代码注释,然后理清基本思路和步骤。

下面是我的做法:
# 抢红包 v0.8 
import random
def hongbao(total, num):  # 发多少钱的红包,有多少个人抢红包
    while True:
        each = random.choices(range(1, total), k=num)  # 存储每个人分别抢到了多少
        if sum(each) == total:  
            break # 保证总和为红包金额,才退出循环
    return each

print(hongbao(10, 5))  # 测试:发10块钱红包,5个人抢(每个人都有)

#注: 用randint等随机生成再验证,似乎效率很低,难以保证快速生成总和为红包金额的each序列。
     故采用了choices(),它的效率足够。

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-6-7 16:29:55 | 显示全部楼层    本楼为最佳答案   
本帖最后由 qq1151985918 于 2021-6-7 16:40 编辑
# 首先要看懂整片代码的意义,得一句一句代码分析
# 并且揣摩写代码人的用意
# 这个代码是有比较明显缺陷的
# 缺陷就是 越是前边领取红包的人领取的金额越大
# 越是后边领取红包的人领取的金额越小
# 代码案例中 取 num = 5 就已经很明显了
# 预计代码如果取 num = 20 就没法看了

# 加载模块
import random

# 定义函数 total 为红包总金额 num 为红包个数
def hongbao(total,num):
    
    # each 这里的作用就是储存已经领取的红包金额和人数
    # 如果第一个人领取了 1 块钱,each 就变成 [1]
    # 如果第二个人领取了 2 块钱,each 就变成 [1, 2]
    each=[]
    
    # already 这里的作用是计算已经领取的红包金额
    # 如果第一个人领取了 1 块钱,already 就变成 1
    # 如果第二个人领取了 2 块钱,already 就变成 3
    # total-already 表示剩余未被领取的金额
    already=0

    # 这里用的 range(1,num) 其实是有深意的
    # 故意少算了一个红包,因为用这个代码
    # 无法保证最后一个人拿到全部的剩余金额
    # 所以在最后又单独加了一个 each.append(total-already)
    # 将全部剩余金额都分配给最后领取的人
    for i in range(1,num):

        # 我们知道 randint 的取值是比较特殊的
        # 一般我们认知的取值区间都是 左闭右开
        # 但是 randint 的取值是 全闭区间
        # 这也是为什么在上面说的要把红包分配少一个人的原因之一
        # 也是下边代码 最后 -(num-i) 的原因
        # 写代码的人的想法是,要保证领取红包的人最少能够领取 1 元
        # 不知道你能不能看懂
        # 全部代码最有深度的就是下边的这一行代码
        # 一定要把这一行代码吃透
        # 这一行代码保证了每个领取到红包的人最少领取到 1 块钱
        # total-already 表示剩余未领取的钱
        # range(1,num) 是取不到 num 的值的,只能取到 num - 1
        # 如果确实看不懂再问吧
        t=random.randint(1,(total-already)-(num-i))

        # 将已经领取的红包储存
        each.append(t)

        # 更新已经领取的金额 already
        already=already+t

    # 将最后剩余金额全部分配给最后一个领取到红包的人
    each.append(total-already)
    
    # 将红包信息返回
    return each
if __name__=='__main__':
    total=300
    num=5

    # 模拟 10 次红包 均为 300 元 5 人
    for i in range(10):
        each=hongbao(total,num)
        print(each)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-15 13:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表