Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 4041|回复: 12

[已解决]微信,qq红包随机问题怎么用excel模拟

[复制链接]
发表于 2017-9-25 15:15 | 显示全部楼层 |阅读模式
如10元发5个包,5个是随机数的带2位小数,总和等于10元,用函数,vba或者power query等不限制方法
最佳答案
2017-9-25 17:15
本帖最后由 小新De和尚头 于 2017-9-25 17:30 编辑
  1. Sub GetRandomMoney(r As RedPackage)
  2.     For i = 1 To r.remainSize
  3.         If r.remainSize = 1 Then
  4.             r.remainSize = r.remainSize - 1
  5.             Debug.Print Round(r.remainMoney * 100) / 100
  6.             Exit Sub
  7.         End If
  8.         Dim min As Double
  9.         Dim max As Double
  10.         Dim money As Double
  11.         min = 0.01
  12.         max = r.remainMoney / r.remainSize * 2
  13.         Randomize
  14.         money = Rnd * max
  15.         If money <= min Then
  16.             money = 0.01
  17.         End If
  18.         money = Fix(money * 100) / 100
  19.         r.remainSize = r.remainSize - 1
  20.         r.remainMoney = r.remainMoney - money
  21.         Debug.Print money
  22.     Next
  23. End Sub

  24. Sub test()
  25.     Dim r As New RedPackage
  26.     r.remainMoney = 1
  27.     r.remainSize = 3
  28.     Call GetRandomMoney(r)
  29.     '结果请在立即窗口里查看
  30. End Sub
复制代码
测试结果
p1.png P2.png


excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2017-9-25 15:30 | 显示全部楼层
不玩微信,不知道对不对。
  1. Sub aaa()
  2. Dim n#, arr(1 To 5), i&, m#
  3. Randomize
  4. n = 10
  5. For i = 1 To 4
  6.   m = Format(Rnd() * n, "0.00")
  7.   arr(i) = m
  8.   n = n - m
  9. Next i
  10. arr(5) = n
  11. [a1].Resize(, 5) = arr
  12. End Sub
复制代码

评分

参与人数 1 +12 收起 理由
苏子龙 + 12 赞一个,还有点问题,思路差不多

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2017-9-25 16:41 | 显示全部楼层
本帖最后由 苏子龙 于 2017-9-26 08:30 编辑
  1. Sub RedPackage()
  2.     Dim ar(), SumHe#, i%, n%, TemCount
  3.     Dim RedPkgMoney#, RedPkgCount%, TemMaxMoney%
  4.     RedPkgMoney = [c2]: RedPkgCount = [d2] '初始化,提取红包数据并判断
  5.     If RedPkgMoney = 0 Or RedPkgCount = 0 Then Exit Sub
  6.     If RedPkgMoney > 200 Then MsgBox "最大200元": Exit Sub
  7.     If RedPkgCount > 100 Then MsgBox "最多发100个": Exit Sub
  8.     If RedPkgMoney / RedPkgCount < 0.01 Then MsgBox "最少发0.01元": Exit Sub
  9.     ReDim ar(1 To RedPkgCount, 1 To 3) '定义数组,1是随机金额,2辅助排序,3最后的金额
  10.    
  11.     For i = 1 To RedPkgCount - 1 '循环数量-1
  12.         TemCount = Int(Rnd * (RedPkgCount - i - 1)) + 1 '随机分多少次
  13.         TemMaxMoney = RedPkgMoney * 100 - SumHe * 100 - RedPkgCount + i  '随机临时本次最大金额
  14.         TemMaxMoney = Int(TemMaxMoney / TemCount) '再随机取最大金额
  15.         TemMaxMoney = IIf(TemMaxMoney < 1, 1, TemMaxMoney) '判断:最少分的0.01元
  16.         ar(i, 1) = Application.RandBetween(1, TemMaxMoney) / 100 '随机金额
  17.         SumHe = ar(i, 1) + SumHe '已分金额总计
  18.     Next
  19.     ar(RedPkgCount, 1) = RedPkgMoney - SumHe '最后分的金额
  20.     i = 1 '用do,loop循环,已分金额再随机排序
  21.     Do While i <= RedPkgCount
  22.         n = Int(Rnd * RedPkgCount) + 1
  23.         If ar(n, 2) = "" Then
  24.             ar(n, 2) = n
  25.             ar(i, 3) = ar(n, 1)
  26.             i = i + 1
  27.         End If
  28.     Loop
  29.     Range("a:a").ClearContents
  30.     Range("a1").Resize(RedPkgCount, 1) = Application.Index(ar, , 3)
  31. End Sub
复制代码


常规想法做的vba

QQ红包.zip

10.52 KB, 下载次数: 8

更改错误的地方

回复

使用道具 举报

发表于 2017-9-25 17:15 | 显示全部楼层    本楼为最佳答案   
本帖最后由 小新De和尚头 于 2017-9-25 17:30 编辑
  1. Sub GetRandomMoney(r As RedPackage)
  2.     For i = 1 To r.remainSize
  3.         If r.remainSize = 1 Then
  4.             r.remainSize = r.remainSize - 1
  5.             Debug.Print Round(r.remainMoney * 100) / 100
  6.             Exit Sub
  7.         End If
  8.         Dim min As Double
  9.         Dim max As Double
  10.         Dim money As Double
  11.         min = 0.01
  12.         max = r.remainMoney / r.remainSize * 2
  13.         Randomize
  14.         money = Rnd * max
  15.         If money <= min Then
  16.             money = 0.01
  17.         End If
  18.         money = Fix(money * 100) / 100
  19.         r.remainSize = r.remainSize - 1
  20.         r.remainMoney = r.remainMoney - money
  21.         Debug.Print money
  22.     Next
  23. End Sub

  24. Sub test()
  25.     Dim r As New RedPackage
  26.     r.remainMoney = 1
  27.     r.remainSize = 3
  28.     Call GetRandomMoney(r)
  29.     '结果请在立即窗口里查看
  30. End Sub
复制代码
测试结果
p1.png P2.png


1.png

红包随机算法.rar

15.75 KB, 下载次数: 17

评分

参与人数 2 +42 金币 +30 收起 理由
心正意诚身修 + 30 + 30 老子好久没有听小杰唱歌了。
苏子龙 + 12 我和小伙伴都惊呆了

查看全部评分

回复

使用道具 举报

 楼主| 发表于 2017-9-26 13:16 | 显示全部楼层
结合2,4楼的代码
Sub aaa()
    Dim Money As Double, arr(), iCount As Integer 'money是余额,arr存放分得的金额,icount是循环数
    Dim TemMoney As Double, Max As Double 'temmoney随机金额,max是可以分的最大金额
    Const Min As Double = 0.01 '定义常量:最小额
    Dim RedPackageMoney As Double, RedPackageCount As Integer '红包金额和个数
   
    RedPackageMoney = Range("C2").Value
    RedPackageCount = Range("D2").Value
    If RedPackageMoney > 200 Then MsgBox "金额不能大于200元": Exit Sub
    If RedPackageCount > 100 Then MsgBox "红包个数不能大于100个": Exit Sub
    If RedPackageMoney / RedPackageCount < Min Then MsgBox "输入不对": Exit Sub
    ReDim arr(1 To RedPackageCount, 1 To 1)
    Money = RedPackageMoney '初始将红包里的钱放入money,作为剩余金额
    Randomize
    For iCount = 1 To RedPackageCount '循环判断
        If iCount = RedPackageCount Then '当最后一个时,就运行最后一步
            arr(iCount, 1) = Application.Round(Money, 2)
            Range("a:a").ClearContents
            Range("a1").Resize(RedPackageCount) = arr
            Exit Sub
        End If
        Max = Money / (RedPackageCount - iCount + 1) * 2 '平分
        TemMoney = Fix(Rnd * Max * 100) / 100       '随机取值,fix同int
        If TemMoney < Min Then TemMoney = Min  '当小于最小值时,取最小值
        arr(iCount, 1) = TemMoney
        Money = Money - TemMoney          '累计剩余金额
    Next iCount
End Sub
回复

使用道具 举报

 楼主| 发表于 2017-9-26 16:16 | 显示全部楼层
本帖最后由 苏子龙 于 2017-9-26 16:28 编辑
  1. Dim Je As Double, Ncount As Integer, arr(1 To 100)
  2. Sub test()
  3.     Dim RedPackageMoney As Double, RedPackageCount As Integer '红包金额和个数
  4.     RedPackageMoney = Range("C2").Value
  5.     RedPackageCount = Range("D2").Value
  6.     If RedPackageMoney > 200 Then MsgBox "金额不能大于200元": Exit Sub
  7.     If RedPackageCount > 100 Then MsgBox "红包个数不能大于100个": Exit Sub
  8.     If RedPackageMoney / RedPackageCount < Min Then MsgBox "输入不对": Exit Sub
  9.     Ncount = RedPackageCount
  10.     Je = RedPackageMoney
  11.     Call digui(Je)
  12.     Range("a:a").ClearContents
  13.     Range("a1").Resize(RedPackageCount) = Application.Transpose(arr)
  14. End Sub

  15. Sub digui(M)
  16.     Dim max As Double
  17.     max = Je / Ncount * 2
  18.     max = Int(Rnd * max * 100) / 100
  19.     If max < 0.01 Then max = 0.01
  20.    
  21.     If Ncount = 1 Then '退出条件***
  22.         arr(Ncount) = Application.Round(Je, 2)
  23.         Exit Sub
  24.     End If
  25.    
  26.     arr(Ncount) = max
  27.     Je = Je - max
  28.     Ncount = Ncount - 1
  29.     Call digui(Je)
  30. End Sub
复制代码

学习递归,用递归替代for,next循环
回复

使用道具 举报

发表于 2017-9-27 17:10 | 显示全部楼层
说了这么久,红包呢,在哪里呀
回复

使用道具 举报

 楼主| 发表于 2017-9-28 13:49 | 显示全部楼层
hhzjxss 发表于 2017-9-27 17:10
说了这么久,红包呢,在哪里呀

{:011:}加qq群后才能发吧
回复

使用道具 举报

 楼主| 发表于 2017-9-28 15:47 | 显示全部楼层
今天搬来了江苏大侠的函数公式
  1. =IF(ROW()<C7+8,IFERROR(FREQUENCY(ROW(INDIRECT("1:"&C8/1%-C7)),RANDBETWEEN(ROW(INDIRECT("1:"&C7-1))*0,C8/1%-C8)),)%+1%,"")
复制代码

具体见附件

拼手气红包.zip

26.28 KB, 下载次数: 17

回复

使用道具 举报

 楼主| 发表于 2017-9-28 16:10 | 显示全部楼层
本帖最后由 苏子龙 于 2017-9-28 16:21 编辑

上面函数,如果是一个包时,会出错,就再加个判断
  1. =IF(ROW()<C7+8,IF(C7=1,C8,IFERROR(FREQUENCY(ROW(INDIRECT("1:"&C8/1%-C7)),RANDBETWEEN(ROW(INDIRECT("1:"&C7-1))*0,C8/1%-C8)),)%+1%),"")
复制代码


其原理是用到了frequency函数的特性,fre。是取数的频率次数,如只有3个数时
=frequency(row(1:10),{2,5}),其结果是{2,3,5},正好是要的金额,2,5位置不同结果位置跟着变,但结果的和还是10
本例中fre第一参数ROW(INDIRECT("1:"&C8/1%-C7)),金额放大100倍,就是金额变成整数,减个数就是减1分钱,后面再加上1分钱,总数不变,而且为了防止错误时起码还有1分钱存在
fre。第二参数是用randbetween去个数-1的随机数(0~金额*100-金额),减金额是防止正好随机到最大数。

回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-24 08:51 , Processed in 0.346578 second(s), 15 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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