ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 6871|回复: 37

[原创] n取m 自定义函数 随机 组合 排列 分组 分配

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2020-3-19 09:57 | 显示全部楼层 |阅读模式
本帖最后由 yjh_27 于 2020-4-22 16:32 编辑

从n 个数(元素)中取m个,有几大类:
一  随机取
二  一次取m个
      按只看结果不看过程:组合。不分抽取先后,无顺序
      既看结果又看过程:排列。抽取先后不同,结果不同。有顺序。
三 分k次,每次取m1、m2、....mk个。称为分组问题
     分组问题属于组合问题,一般与顺序无关
     或者说,将n个数(元素)分成k堆,称为分组问题
     n个不同元素按照某些条件分配给k个不同得对象,称为分配问题
四 一次取m个极值(最大、最小)


针对以上问题,做了数个自定义函数。见附件。
具体使用方法分别介绍



n个元素中抽出m个元素(V1.2).rar

407.62 KB, 下载次数: 182

m<0时,取n个(全取)

n个元素中抽出m个元素(V1.21).rar

381.53 KB, 下载次数: 208

评分

7

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:05 | 显示全部楼层
一   随机抽取
n中随机取m,一次。取出的无重复
  1. '*********************yjh_27****2020.3.19******************************
  2. '功能:    从n个中随机取不重复m个,以一维数组返回
  3. '函数名:  ArrRnd0
  4. '
  5. '参数1:n       元素数
  6. '参数2:m       抽取数量
  7. '参数3:n0      元素起始数(最小数)
  8. '参数4:m0      输出数组下标、元素数组下标
  9. '
  10. '返回值:  一维数组
  11. '使用方法:kclmr = ArrRnd0(5,2)
  12. '
  13. Function ArrRnd0(n As Long, m As Long, Optional n0 = 1, Optional m0 = 0)

  14. n1 = n + n0 - 1
  15. m1 = m + m0 - 1
  16. ReDim arr(n0 To n1)
  17. ReDim brr(m0 To m1)
  18. For i = n0 To n1
  19.     arr(i) = i
  20. Next
  21. Randomize
  22. For i = m0 To m1
  23.     k = i + n0 - m0
  24.     j = Int(Rnd * (n1 - k + 1)) + k
  25.     brr(i) = arr(j)
  26.     arr(j) = arr(k)
  27.     arr(k) = brr(i)
  28. Next
  29. ArrRnd0 = brr
  30. End Function
复制代码
n中随机取m,一次。取出的可重复
  1. '*********************yjh_27****2020.3.19******************************
  2. '功能:    从n个中随机取可重复m个,以一维数组返回
  3. '函数名:  Arr2Rnd0
  4. '
  5. '参数1:n       元素数
  6. '参数2:m       抽取数量
  7. '参数3:n0      元素起始数(最小数)
  8. '参数4:m0      输出数组下标、元素数组下标
  9. '
  10. '返回值:  一维数组
  11. '使用方法:kclmr = Arr2Rnd0(5,2)
  12. '
  13. Function Arr2Rnd0(n As Long, m As Long, Optional n0 = 1, Optional m0 = 0)
  14. If n0 <> 0 Then n0 = 1
  15. n1 = n + n0 - 1
  16. m1 = m + m0 - 1
  17. ReDim brr(m0 To m1)
  18. Randomize
  19. For i = m0 To m1
  20.     j = Int(Rnd * (n1 - n0 + 1)) + n0
  21.     brr(i) = j
  22. Next
  23. Arr2Rnd0 = brr
  24. End Function
复制代码


评分

3

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:07 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 yjh_27 于 2020-4-25 10:27 编辑

n中随机取m,一次。取出的不 重复
按行输出  r=1
按列输出 c=1
  1. '*********************yjh_27****2020.3.19******************************
  2. '功能:    从n个中随机取不重复r*c个,以二维数组r行c列返回
  3. '函数名:  ArrRnd20
  4. '需要 ArrRnd0 函数
  5. '
  6. '参数1:n       元素数
  7. '参数2:r       输出数组行数
  8. '参数3:c       输出数组列数
  9. '参数4:n0      元素起始数(最小数)
  10. '参数5:m0      输出数组下标、元素数组下标
  11. '
  12. '返回值:  二维数组
  13. '使用方法:kclmr = ArrRnd20(5,2)
  14. '
  15. Function ArrRnd20(n As Long, r As Long, c As Long, Optional n0 = 1, Optional m0 = 0)

  16. Dim m As Long
  17. m = r * c
  18. If n < m Then n = m
  19. r1 = r + m0 - 1
  20. C1 = c + m0 - 1
  21. crr = ArrRnd0(n, m, n0, m0)
  22. ReDim brr(m0 To r1, m0 To C1)
  23. ci = m0
  24. For i = m0 To r1
  25. For j = m0 To C1
  26.     brr(i, j) = crr(ci)
  27.     ci = ci + 1
  28. Next
  29. Next
  30. ArrRnd20 = brr
  31. End Function
复制代码
n中随机取m,一次。取出的可 重复
  1. '*********************yjh_27****2020.3.19******************************
  2. '功能:    从n个中随机取可重复r*c个,以二维数组r行c列返回
  3. '函数名:  Arr2Rnd20
  4. '需要 Arr2Rnd0 函数
  5. '
  6. '参数1:n       元素数
  7. '参数2:r       输出数组行数
  8. '参数3:c       输出数组列数
  9. '参数4:n0      元素起始数(最小数)
  10. '参数5:m0      输出数组下标、元素数组下标
  11. '
  12. '返回值:  二维数组
  13. '使用方法:kclmr = Arr2Rnd20(5,2)
  14. '
  15. Function Arr2Rnd20(n As Long, r As Long, c As Long, Optional n0 = 1, Optional m0 = 0)

  16. Dim m As Long
  17. m = r * c
  18. If n < m Then n = m
  19. r1 = r + m0 - 1
  20. C1 = c + m0 - 1
  21. crr = Arr2Rnd0(n, m, n0, m0)
  22. ReDim brr(m0 To r1, m0 To C1)
  23. ci = m0
  24. For i = m0 To r1
  25. For j = m0 To C1
  26.     brr(i, j) = crr(ci)
  27.     ci = ci + 1
  28. Next
  29. Next
  30. Arr2Rnd20 = brr
  31. End Function
复制代码


应用求随机数的生成
http://club.excelhome.net/thread-1533777-1-1.html
(出处: ExcelHome技术论坛)
=ArrRnd20(999999,100,8)


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2020-3-19 10:09 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
占个沙发  

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:19 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 yjh_27 于 2020-3-19 10:20 编辑

以上只能对 “数”,进行抽取,但经常需要对元素进行抽取
同样分四中情况。
分别为:
ArrRnd
'功能:    从n个中随机取不重复m个,以一维数组返回
'函数名:  ArrRnd


Arr2Rnd
'功能:    从n个中随机取可重复m个,以一维数组返回
'函数名:  Arr2Rnd


ArrRnd2
'功能:    从n个中随机取不重复r*c个,以二维数组r行c列返回
'函数名:  ArrRnd2


Arr2Rnd2
'功能:    从n个中随机取可重复r*c个,以二维数组r行c列返回
'函数名:  Arr2Rnd2



代码见1L附件   随机n取m  模块



评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2020-3-19 10:26 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:28 | 显示全部楼层
随机取数,除了重复、不重复;一次、数次。有时还有其他限制

这时使用
'*********************yjh_27****2020.3.19******************************
'功能:    从n个中随机取r*c个,以二维数组返回
'函数名:  Arr2Rnd2x
'需要 nyuchuli 过程
'
'参数1:n       每列元素,不限于数字;n>r;n>c,有时会无结果
'参数2:r       输出数组行数
'参数3:c       输出数组列数
'参数4:n0      元素起始数(最小数)
'参数5:m0      输出数组下标、元素数组下标
'参数6:mode    抽取模式
'           =0    每列不重复
'           =1    每行、每列不重复
'           =2    每行、每列不重复,各列之间无相同的 正向行间相邻数。
'           =3    每行、每列不重复,各列之间无相同的 行间相邻数。
'           =4    每行、每列不重复,各行之间无相同的 正向列间相邻数。
'           =5    每行、每列不重复,各行之间无相同的 列间相邻数。
'           =6    每行、每列不重复,各列之间无相同的 正向行间相邻数。各行之间无相同的 正向列间相邻数。
'           =7    每行、每列不重复,各列之间无相同的 行间相邻数。各行之间无相同的 列间相邻数。
'
'返回值:  二维数组返回随机数
'使用方法:kclmr = Arr2Rnd2x(5,2)

题目来源
随机数字
http://club.excelhome.net/thread-1522210-1-1.html
(出处: ExcelHome技术论坛)




评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:34 | 显示全部楼层
本帖最后由 yjh_27 于 2020-4-22 16:19 编辑

随机告一段落

下面介绍组合、排列
'*********************yjh_27****2020.3.19******************************
'功能:    n元素(数)取m个,排列组合
'           n【参数1】个连续的自然数,任取m【参数2】个,共有几种取法
'函数名:  ArrPC
'需要   nyuchuli 过程
'需要   cc 函数
'
'参数1:n       元素
'参数2:m       抽取数量
'参数3:mode    模式
'           mode个位
'           1       不考虑顺序不可重复(组合):C(n,m)=n!/m!(n-m)!
'           2       不考虑顺序且可重复:C(n+m-1,m) =(n+m-1)!/m!(n-1)!
'           3       考虑顺序不可重复(排列):P(n,m)=n!/(n-m)!
'           4       考虑顺序且可重复(m位n进制):n^m
'           5       没有相邻的数字组合:C(n-m+1,m)=(n-m+1)!/[(n-2m+1)!m!]
'           6       要求取出连续自然数组合:C(n-m+1,1)=n-m+1
'           7       从不取到取m个,取n时(全组合):2^n
'           mode十位
'           mode=1~9    输出二维数组
'           mode=11~19  输出单列,","连接各列
'           mode=21~29  输出单列," "连接各列
'           mode=31~39  输出单列,"."连接各列
'           mode=41~49  输出单列,""连接各列
'参数4:n0      元素起始数(最小数)
'           n为字符时:
'           =1      以"," 分列n
'           =2      以" " 分列n
'           =3      以"." 分列n
'           n为数组时:
'           =0      全部为n【参数1】;
'           >0      n0列的各行 为n【参数1】;
'           <0      n0行的各列 为n【参数1】
'参数5:m0      输出数组下标、元素数组下标
'参数6:ncf     各组取法中同列元素可重复次数,mode=2、3、4
'           0      不限制可重复次数
'           >0     可重复次数
'参数7:mcf     一组取法中元素可重复次数,mode=2、4
'           mode=2时,>0
'           mode=4时,>0 重复可相邻;<0 重复不相邻
'参数8:nscf    各组取法中元素可重复次数,mode=2、3、4
'           0      不限制可重复次数
'           >0     可重复次数
'
'返回值:  多列排列组合数组
'使用方法:kclmr = ArrPC(5,2,3)
'


应用
最大组合数   4L
http://club.excelhome.net/thread-1533230-1-1.html
(出处: ExcelHome技术论坛)

1-20中任意5个数相加,这样的排列组合能否用VBA实现  15L
http://club.excelhome.net/thread-1532781-1-1.html
(出处: ExcelHome技术论坛)




评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:42 | 显示全部楼层
指定组合、排列结果查序号(索引号)

指定序号(索引号)查组合、排列结果

这个有前提,所有组合结果,已按从小到大排序。
不是公认的。主要用于随机抽取组合时使用。大组合量时不需(不能)列出所有组合结果
'*********************yjh_27****2020.3.19******************************
'功能:    n个连续的自然数,任取m个,返回第k种取法
'           已知序号求排列组合结果的自定义函数
'           所有组合结果,已按从小到大排序。
'函数名:  SeqNumPC
'
'参数1:n       元素
'参数2:m       抽取数量
'参数3:mode    模式
'           mode个位
'           1       不考虑顺序不可重复(组合):C(n,m)=n!/m!(n-m)!
'           2       不考虑顺序且可重复:C(n+m-1,m) =(n+m-1)!/m!(n-1)!
'           3       考虑顺序不可重复(排列):P(n,m)=n!/(n-m)!
'           4       考虑顺序且可重复(m位n进制):n^m
'           5       没有相邻的数字组合:C(n-m+1,m)=(n-m+1)!/[(n-2m+1)!m!]
'           6       要求取出连续自然数组合:C(n-m+1,1)=n-m+1
'           7       从不取到取n个(全组合):2^n
'           mode十位
'           mode=1~9    输出二维数组
'           mode=11~19  输出单列,","连接各列
'           mode=21~29  输出单列," "连接各列
'           mode=31~39  输出单列,"."连接各列
'           mode=41~49  输出单列,""连接各列
'参数4:k       排列、组合序号(索引)ID
'参数5:n0      元素起始数(最小数),n为字符时:<>2,以" " 分列n;=2,以"," 分列n
'参数6:k0      顺序号起始数(最小数)
'
'返回值:  多列排列组合数组
'使用方法:kclmr = SeqNumPC(49, 6, 11, 13789132)
'



'*********************yjh_27****2020.3.19******************************
'功能:    n个连续的自然数,任取m个,已知组合结果,求第k个序号
'           所有组合结果,已按从小到大排序。
'函数名:  PCSeqNum&
'
'参数1:s       组合结果
'参数2:n       元素数
'参数3:mode    模式
'           mode个位
'           1       不考虑顺序不可重复(组合):C(n,m)=n!/m!(n-m)!
'           2       不考虑顺序且可重复:C(n+m-1,m) =(n+m-1)!/m!(n-1)!
'           3       考虑顺序不可重复(排列):P(n,m)=n!/(n-m)!
'           4       考虑顺序且可重复(m位n进制):n^m
'           5       没有相邻的数字组合:C(n-m+1,m)=(n-m+1)!/[(n-2m+1)!m!]
'           6       要求取出连续自然数组合:C(n-m+1,1)=n-m+1
'           7       从不取到取n个(全组合):2^n
'           mode十位
'           mode=1~9    输出二维数组
'           mode=11~19  输出单列,","连接各列
'           mode=21~29  输出单列," "连接各列
'           mode=31~39  输出单列,"."连接各列
'           mode=41~49  输出单列,""连接各列
'参数4:n0      元素起始数(最小数),n为字符时:<>2,以" " 分列n;=2,以"," 分列n
'参数5:k0      顺序号起始数(最小数)
'
'返回值:  多列排列组合数组
'使用方法:kclmr = PCSeqNum("24 29 33 37 40 45", 49)
'
'

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-3-19 10:45 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 yjh_27 于 2020-3-19 19:27 编辑

image.png
在n取m分k组  模块中,
有个精简的组合排列自定义函数ArrPC0,可独立应用。

分组分配自定义函数ArrGC,是费时最长的。
分组:又分为不平均分组、平均分组、部分平均分组。
计算时,要先算不平均分组、后算平均分组。当然也可以反过来。
但是不能交叉计算。

其中平均分组有难度,特别是元素没有用完的平均分组。
我的处理方法是先抽取平均分组所需元素,再按全部元素使用的平均分组。

题目来源
10个数字分成5组列出所有组合,谢谢
http://club.excelhome.net/thread-1414052-1-1.html
(出处: ExcelHome技术论坛)
原帖没有(正确)解决问题

求助大神棘手难题:数列组合运算,找出数列中运算结果小于误差的所有组合。
http://club.excelhome.net/thread-1523421-1-1.html
(出处: ExcelHome技术论坛)


代码详见附件。
其中
bjs = Array(2, 2, 2, 3, 3)
js = Array(0, 1, 2, 0, 2)

定义了计算分配。对应修改即可计算不同的分配。


数列组合计算.rar

107.97 KB, 下载次数: 47

评分

3

查看全部评分

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

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-5-22 23:01 , Processed in 0.049136 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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