zjzjzjzjx 2023-12-10 21:18 采纳率: 33.3%
浏览 25

python 随机红包金额拆分

【任务描述】
微信红包是十分受大家欢迎的功能,其核心任务是要将给定的金额随机拆分成给定个数的红包。也就是说将给定的待发红包金额和个数按随机的方式确定每个红包的金额。编程实现该功能。
【输入】
第一行有一个正整数,表示测试用例的个数。其后的每行有两个数据,分别表示红包的金额和个数,用空
格分隔。发红包的金额,单位为元(最大金额2万元,可能有2位小数),红包个数为小于500个的正整数(一个社交群通常不会超过 500 人)。发红包的总金额不会低于每个红包1分钱。
【输出】
每个测试用例输出一行。
对于每个测试用例,输出每个红包的金额,单位为元,保留2位小数,用空格分隔。
多次运行相同红包金额和个数时,结果应该体现随机性。发放的红包总金额必须等于所有红包金额之和,不得有误差。
输入举例:
5
10 3
0.05 5
0.03 2
0.17 1
0.01 1
输出举例:
(此空行不应输出,在此仅为方便对齐看结果)
1.84 6.78 1.38
0.01 0.01 0.01 0.01 0.01
0.02 0.01
0.17
0.01
分析:
红包拆分方式有很多种,以下方式供参考。
在本编程任务中,如果对红包金额直接按浮点数型数据进行处理,有可能导致最终结果存在误差,这是有浮点数类型本身的特点决定的。因此,为了无误差地将总金额拆分到指定个数的红包中,需要将输入的带小数点的金额转换为整数,将以"元"为单位转换为以"分"诶单位。故红包金额都以"分"为单位进行存储和运算,输出时在转换为以"元"为单位的结果显示。
在整个红包分配过程中,为了防止某个红包的金额为0,便为每个红包保底1分钱,这个1分钱的保底金额是不参与红包金额随机调整的,是固定不变的。此外,这1分钱的保底金额在计算过程中并不体现在每个红包的值之中,但在最终输出时,这个1分钱的保底金额必须体现在每个红包的最终金额中。在此假定以"分"为单位的待分总金额为k,红包个数为n。程序设计如下:
首先,为红包分配初始金额,其目标是尽量平均地将总金额分配到每个红包。具体做法是:将待分总金额k,按n份平分,每份为k//n-1。如果还有剩余,那么将前k%n个红包金额每个增加1。例如,k=206,n=4则此时4个红包的金额分别是51,51,50,50。
然后,随机选择两个红包,将两个红包的金额合并,接着随机地拆分后放回到这两个红包,调整前、后两个红包的金额保持不变。此操作重复若干次,就能达到红包金额随机分配的效果。具体重复多少次,可以设计自己的计算方式。在此采用计算式k//(n*10)+1来确定,并且最少重复10次。
最后,输出时,给每个红包加上未参与运算的保底金额。
显然,当红包个数为1时,就不需要以上随机拆分金额的过程。
【重要知识点】
(1) 如何尽量将带有小数的运算转换为整数运算。
(2)
random 库中的随机数函数的运用。
(3)
如何实现固定金额的随机分配。

  • 写回答

3条回答 默认 最新

  • 梦幻精灵_cq 2023-12-14 06:53
    关注
    • 用一个随机整数方法random.randint就够了

      关键点一:要把金额乘以100变成整型来让python运算,才不会“失真”;

      关键点二:用金额和红包个数来确定红包金额随机区间。

      img


      关于代码实现,可以递归也可以循环;关于数据输出可以直接打印也可以先存储最后一起打印。

    python代码(递归)

    #!/sur/bin/nve python
    # coding: utf-8
    from random import randint
    
    def splitRedenvelope(money, num):
        ''' 拆分红包 '''
        
        if not money%num:
            print(*[money/num/100]*num, end='\n')
            return 
        else:
            n = int(money/num) if not money%num else int(money/num)+1
            one = randint(1, n)
            print(one/100, end=' ')
            return splitRedenvelope(money - one, num - 1)
    
    if __name__ == '__main__':
        input_s = '''5
    10 3
    0.05 5
    0.03 2
    0.17 10
    0.01 1'''
        data = input_s.split('\n')[1:]
        for i in range(int(input_s[0])-1):
            money, num = data[i+1].split()
            print(f"\n金额:{money}  拆分红包个数:{num}\n红包金额:", end='')
            splitRedenvelope(int(float(money)*100), int(num))
    
    

    • 发现“算法”漏洞,“0.17 10”的输入样例,没有完全随机

      img


      bug已修复。

    Python代码

    #!/sur/bin/nve python
    # coding: utf-8
    from random import randint
    
    def splitRedenvelope(money, num):
        ''' 拆分红包 '''
        
        if money == num or num == 1:
            print(*[money/num/100]*num, end='\n')
            return 
        else:
            one = randint(1, money - num)
            print(one/100, end=' ')
            return splitRedenvelope(money - one, num - 1)
    
    if __name__ == '__main__':
        input_s = '''5
    10 3
    0.05 5
    0.03 2
    0.17 10
    0.01 1'''
        data = input_s.split('\n')[1:]
        for i in range(int(input_s[0])):
            money, num = data[i].split()
            print(f"\n金额:{money}  拆分红包个数:{num}\n红包金额:", end='')
            splitRedenvelope(int(float(money)*100), int(num))
    
    

    感觉问题有些细节,我会将回答抽空整理成学习笔记,了解更多细节,请移步学习笔记


    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 12月10日
  • 创建了问题 12月10日

悬赏问题

  • ¥15 Django DRF 如何反序列化得到Python对象类型数据
  • ¥15 多数据源与Hystrix的冲突
  • ¥15 如何在线硕士了解,广告太多,希望有真实接触过的人回答下?(标签-学习|关键词-在线硕士)
  • ¥15 h5页面 使用u-upload 组件上传图片,如何解决,安卓系统不支持选择多张图片
  • ¥15 zabbix6.4与frp如何进行联动
  • ¥15 如何使用Echarts制作途中时间序列表
  • ¥15 图论相关的数学问题,共10个
  • ¥15 EtherCAT的问题,创建一个XML文件
  • ¥15 微信公众号羽毛球自动抢定场程序制作
  • ¥15 Fluent UDF 编写