ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 快速生成m位 l - n 区间内(n +1)进制数全部组合的自定义函数

[复制链接]

TA的精华主题

TA的得分主题

发表于 2014-8-14 16:44 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:自定义函数开发
本帖最后由 香川群子 于 2014-8-22 13:49 编辑

比如,生成十进制(最大元数n=9)的4位数 0000 - 9999

或 五进制 (最大元数n=4)的4位数 0000 - 4444 (0005、2345等超过最大元素4的数不合法,要排除)

或 二进制 (最大元数n=1)的8位数 0000 0000 - 1111 1111


代码如下:

  1. Sub GetSeqTest()
  2.     tms = Timer
  3.     ar1 = GetSeqArr(8, 1) '生成 8位 二进制(区间0-1、最大n=1)的数的集合
  4.     ar2 = GetSeqArr(4, 4) '生成 4位 五进制(区间0-4、最大n=4)的数的集合
  5.     ar3 = GetSeqArr(4, 9) '生成 4位 十进制(区间0-9、最大n=9)的数的集合

  6.     ar4 = GetSeqArr(4, 2, 1) '生成 4位 准二进制(区间1-2、最大n=2、最小 l =1 )的数的集合
  7.     ar5 = GetSeqArr(4, 6, 2) '生成 4位 准五进制(区间2-6、最大n=6、最小 l =2 )的数的集合
  8.     '如果实际是要在VBA代码过程中使用,则无需输出结果。


  9.     '下面是输出例子-1 如实际是在VBA中代码过程中使用,则无需输出
  10.     arr = GetSeqArr(3, 9) '生成 3位 十进制(区间0-9、最大n=9)的数的集合、并输出结果到工作表   
  11.     [a1].CurrentRegion = "": [a1].Resize(UBound(arr), UBound(arr, 2)) = arr '输出000 - 999 共1000个数
  12.     MsgBox Format(Timer - tms, "0.000s ") & UBound(arr)

  13.     arr = GetSeqArr(4, 2, 1) '生成 4位 准二进制(区间1-2、最大n=2、最小 l =1)的数的集合、并输出结果到工作表   
  14.     [a1].CurrentRegion = "": [a1].Resize(UBound(arr), UBound(arr, 2)) = arr '输出1111 - 2222 共16个数
  15.     MsgBox Format(Timer - tms, "0.000s ") & UBound(arr)

  16. End Sub

  17. Function GetSeqArr(m&, n&, Optional l& = 0) '自定义函数
  18.     Dim i&, j&, k&
  19.     k = (n - l + 1) ^ m '计算结果总数=区间个数的m次幂

  20.     ReDim a&(k, 1 To m) '定义存放结果的数组a
  21.     For j = 1 To m
  22.         a(0, j) = l: a(k, j) = l '进行初始化赋值 = l (默认=0)
  23.     Next

  24.     For i = 1 To k '遍历产生结果
  25.         For j = m To 1 Step -1 '倒序(实质上是从个位开始升序检查)检查是否需要按n+1进制进位
  26.             If a(k, j) = n Then a(k, j) = l Else a(k, j) = a(k, j) + 1: Exit For
  27.             '如当前位置=进位最大值n 则进位(本位归零 = l 、递归检查上一位) 否则本位+1后结束本次计算赋值
  28.         Next
  29.         '请注意上述处理是在数组最后一行第 k 行进行。 所以最后输出时第k行不要输出的。
  30.   
  31.         '以下把赋值结束后的结果写入结果数组第 i 行
  32.         For j = 1 To m
  33.             a(i, j) = a(k, j)
  34.         Next
  35.     Next
  36.     GetSeqArr = a
  37. End Function
复制代码
我的这个算法,尤其是在数组中的计算过程是超快的。
比String方式合成要快很多倍。

如果只需在VBA代码过程中遍历计算使用,而不需要逐个写入数组,效率会更高。
此时,定义数组a为单行一维数组即可: ReDim a&(1 To m)

补充:
2014年8月22日更新、增加了起始初值 l 的设置(默认 l =0)
这样适用范围更广…………如可以要求从 1111 循环到 4444、或者要求从 2222 循环到 8888


评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-14 16:48 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 香川群子 于 2014-8-22 12:46 编辑

如仅需在VBA代码过程中遍历调用,则过程如下:
  1. Sub CheckSeqArr()
  2.     Dim i&, j&, k&, l&, m&, n&
  3.     m = 4: n = 9: l = 0 '生成4位的0-9区间全部组合数
  4.     k = (n - l + 1) ^ m
  5.     ReDim a&(1 To m)
  6.     For i = 1 To k
  7. '        Check Process 在这里添加你要执行的检查、处理代码
  8.         For j = m To 1 Step -1
  9.             If a(j) = n Then a(j) = l Else a(j) = a(j) + 1: Exit For
  10.         Next
  11.     Next
  12. End Sub
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-14 16:53 | 显示全部楼层
其实我觉得数学界必须更正一个错误的命名方法:

现在流行的n进制,实质上是n-1进制。即每一数位的最大值=n-1

举例:
二进制,实质上是1进制。(逢1进1)
十进制,实质上是9进制。(逢9进1)

八进制,实质上是7进制。(逢7进1)
十六进制,实质上是15进制。(逢15=F进1)

…………
这样就可以解释,为啥世界上最小进制时二进制(实质上是1进制)
而没有一进制! (将变成0进制,逢0进1?无法实现)

呵呵。

但是由于大家都已经习惯了,估计这个概念无法轻易被改正了。





评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-14 16:58 | 显示全部楼层
十进制的逢10进1,是个错误的伪概念,即,个位上的10实际上是虚拟的过程,不会真的发生。
(即因为违反数位上的最大数=9的规则,而无法记录)

实际上准确描述为:
当数位上已经是=最大值 (如=9)时,
该数位上的加法必须进位处理,即:本数位归零=0、下一数位(左边一位高位)数值+1

因此,应该准确描述为: 逢9进1,而不是逢10进1(那个10就是根本不存在的啦!)

点评

我感觉:计数符号的个数、进率可能对于数更为本质……  发表于 2014-8-14 23:14
“数感”的建立是多方面的,一个重要的基础,并且也是难点是:理解数位。数位是数继符号表示后的又一次重要抽象,此时,有限的符号可以表达无穷的数了……  发表于 2014-8-14 23:13
您的“逢9进一”也不怎么完善呀,小学里做4+5=9,您再让进1,那不就是10呢?  发表于 2014-8-14 23:10
十进制的数有10个计数符号,相邻两计数单位的进率是10,这可能是命名“十进制计数法”的原因……  发表于 2014-8-14 23:09

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2014-8-14 23:17 | 显示全部楼层
  能力出众,观念超前,代码神奇,需花时间理解啊……真是超人级别的!

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-15 07:56 | 显示全部楼层
aoe1981 发表于 2014-8-14 23:17
  能力出众,观念超前,代码神奇,需花时间理解啊……真是超人级别的!

【您的“逢9进一”也不怎么完善呀,小学里做4+5=9,您再让进1,那不就是10呢?】

呵呵,你如果不是在开玩笑,那就是语文水平下降……


进位规则中逢9进1的前提是:
进位规则如下:
1. 仅在加法计算过程中使用,任何减法、乘法、除法等其它运算都无关。
2. 这个进位时的加法运算还有如下限制:
  a. 仅在每一个数位上进行,不包括全数位的整体运算。如 120+23这种计算不包括
  b. 仅考虑原数位相加时的变化,默认前提为原数位+1的状态。
     即,只考虑原数位 0-9 分别+1之后的进位状态。不包括0-9 + 2-9 或+0
     (0-9 + 0-9 可以把后加数分解为n次+1过程)
  c. 仅允许两个数相加,不考虑2个以上连续加法运算 如 2+3+4+5+6……

…………
所以,你的问题是无效问题。呵呵。


本数位已经是

点评

没有开玩笑,语文水平有待提高。我只是觉得“逢9进一”可能会产生一些歧义,针对不同的人时。我也能想到您的“原数位+1的状态”,呵呵……  发表于 2014-8-15 18:24

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-15 08:01 | 显示全部楼层
aoe1981 发表于 2014-8-14 23:17
  能力出众,观念超前,代码神奇,需花时间理解啊……真是超人级别的!

【十进制的数有10个计数符号,相邻两计数单位的进率是10,这可能是命名“十进制计数法”的原因】


这个我同意。

但是我发现、或者我觉得这样的命名容易导致错误的理解。
即,每次总是需要把m进制换算为m-1的进位才方便理解。

事实上,我建议,现阶段、可以同时让两种命名方法并存,如:
1进制(二进制)
2进制(三进制)
4进制(五进制)
7进制(八进制)
9进制(十进制)
15进制(十六进制)

…………

点评

抽功夫研究了解下您的本帖代码,否则,所有的回复有点欠基础……猜测,您的新命名是从代码编写的便捷角度出发的吧……  发表于 2014-8-15 18:25

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-15 08:09 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 香川群子 于 2014-8-15 08:12 编辑

下面出几个和进制有关的智力题:

1. 你有3个大瓶子、编号1、2、3(或A、B、C),里面有外观、体积完全相同的白色小药丸 几百个(视作无数个)
2. 已经知道这3个瓶子中的白色小药丸单重不同,分别为1g、2g、3g

问,如何根据一次性称重结果,判明哪个瓶子里装的白色小药丸的规格是几g ?     (即,马上告诉我1号瓶装的药丸是几g、2号瓶装的药丸是几g、3号瓶装的药丸是几g ?)

提示:分别从3个瓶子中取x、y、z粒药丸,一次称重得到总重量H (g),然后根据H来判断。
        

问题-2:
如何定策略(x、y、z的组合方案),可以取用最少的药丸个数,就能达到【一次称重】后根据总重量H的结果来判断?



问题-3:
对于m个瓶子,药丸单重1-m不同时,如何取最少的药丸数量就能一次称重得到判断结果?

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-8-15 09:09 | 显示全部楼层
补充一下,本帖的起因是这个热帖:

【在EXCEL中如何实现4个数为一组,第五个数进位。】
http://club.excelhome.net/thread-1145217-1-1.html

TA的精华主题

TA的得分主题

发表于 2014-8-15 18:33 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 aoe1981 于 2014-8-15 18:34 编辑
香川群子 发表于 2014-8-15 08:09
下面出几个和进制有关的智力题:

1. 你有3个大瓶子、编号1、2、3(或A、B、C),里面有外观、体积完全相同 ...

  此题我没有想到一揽子解决的方法,也就是说可以拓展到m个瓶子的情况。但对于三个瓶子的情况,我凑到了一种结果,见下图:
   1.jpg
  我一开始试了1、2、3,但是有重复,后来,我又猜测的是1、2、4,依次为前面的2倍(这个方法不见得就奏效)……
  目前没有想到和进制的联系……
  还真有点难度啊……


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

本版积分规则

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

GMT+8, 2024-12-31 01:37 , Processed in 0.028889 second(s), 13 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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