ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[Excel 程序开发] [53期国庆附加题] 玩转 N 进制 -----------已结

[复制链接]

TA的精华主题

TA的得分主题

发表于 2009-9-22 23:48 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
VBA只提供了 8  和16进制转换函数,Oct 和 Hex,这是两种在各个领域使用比较多的进制。
到底可以有多少进制?理论上能够找到多少不同字符,就可以有多少进制。
如果用汉字作为进制的表示字符,搞出1000 进制2000进制也不是问题。
这种特殊进制有什么用?别的作用不知道,但最起码起到了数字加密的作用。
FF 这是一个16进制数, 10进制就是255,这对经常和程序打交道的人来说没有秘密,
但对于不懂的人来说这就是天书。
如果借助汉字编写一个188进制的转换函数,对某个数字进行转换后的结果是:
中华人民共和国万岁
是不是很酷?
如果不知道是188进制,也不知道是采用的是哪188个汉字,根本不可能知道这个数字是什么。
题目  2分
编写两个函数,
1.转换Long 值(-2147483648  到 2147483647)为N进制字符串
2.转换N进制字符串 为 Long值(-2147483648  到 2147483647)
要求:纯VBA代码,不得使用API, 不得引用外部对象。常数 Jzs 不得修改。
为使代码简洁、易读,假定传入的参数都是正确合理的,即不会出现 N2ChrX(40000,37) 、
ChrX2N("FFFF",2) 此类参数错误。代码中不需要使用 On Error 语句。
数字0 和 字母 O 看起来很像的问题不用考虑。

评分标准:结果正确、代码效率达到要求,一个函数 1 分

  1. Function N2ChrX(ByVal L As Long, ByVal N As Integer) As String
  2.     '作用:将Long值转换为 N 进制所表示的字符串
  3.     '参数说明 L 要转换的值, N (2-36) 将要使用的进制数
  4.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  5. End Function
  6. Function ChrX2N(ByVal S As String, ByVal N As Integer) As Long
  7.     '作用:字符串值转换为 N 进制所表示的字符串
  8.     '参数说明 S 要转换的N进制字符串, N (2-36) 对S变量进制数的说明
  9.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  10.     S = UCase(S)
  11.    
  12. End Function
  13. '结果正确与否请自行验证,代码效率可用下面代码测试。
  14. Sub 效率验证N2ChrX()
  15.     Dim L As Long, i As Long, v As Long, t As Double, t2 As Double
  16.     t = Timer
  17.     v = 65535
  18.     For i = 1 To 1000000
  19.         S = Hex(v)
  20.     Next
  21.     t = Timer - t
  22.     t2 = Timer
  23.         For i = 1 To (i - 1) / 10
  24.         S = N2ChrX(v, 16)
  25.     Next
  26.     t2 = Timer - t2
  27.     Index = t2 / t * 10 '(越小越好,我的参考指数平均为 15-20 )
  28. MsgBox "代码效率指数为 " & Index & IIf(Index < 100, "   不错!如结果正确可得分", "   太慢了不得分")
  29. End Sub
  30. Sub 效率验证ChrX2N()
  31.     Dim L As Long, i As Long, v As Long, t As Double, t2 As Double
  32.     t = Timer
  33.     v = 65535
  34.     For i = 1 To 1000000
  35.          S = Hex(v)
  36.     Next
  37.     t = Timer - t
  38.     t2 = Timer
  39.     For i = 1 To (i - 1) / 10
  40.         L = ChrX2N("FFFF", 16)
  41.     Next
  42.     t2 = Timer - t2
  43.     Index = t2 / t * 10 '(越小越好,我的参考指数平均为 20-25 )
  44. MsgBox "代码效率指数为 " & Index & IIf(Index < 100, "   不错!如结果正确可得分", "   太慢了不得分")
  45. End Sub

  46. Sub 自检()
  47.     Dim L As Long, L2 As Long, I As Integer, Boo As Boolean, S As String, Lrr(-1000 To 1002) As Long
  48.     V = 65535
  49.     t = Timer
  50.     For L = 1 To 74000
  51.         S = Hex(V)
  52.     Next
  53.     t = Timer - t

  54.     Boo = True
  55.     For L = -1000 To 1000
  56.         Lrr(L) = L
  57.     Next
  58.     Lrr(1001) = -2147483648#
  59.     Lrr(1002) =  2147483647

  60.     t1 = Timer
  61.     For L = -1000 To 1002
  62.         For I = 2 To 36
  63.             L2 = ChrX2N(N2ChrX(Lrr(L), I), I)
  64.             Boo = (Lrr(L) = L2) And Boo
  65.             'If Boo = False Then Stop
  66.         Next
  67.     Next

  68.     For L = -1000 To 1002
  69.         L2 = ChrX2N(Hex(Lrr(L)), 16)
  70.         Boo = (Lrr(L) = L2) And Boo
  71.         'If Boo = False Then Stop
  72.     Next
  73.     For L = -1000 To 1002
  74.         L2 = ChrX2N(Oct(Lrr(L)), 8)
  75.         Boo = (Lrr(L) = L2) And Boo
  76.         'If Boo = False Then Stop
  77.     Next
  78.     t1 = Timer - t1
  79.     Index = t1 / t
  80. Debug.Print "效率指数:" & Index; "   200之内 可以结受"
  81.     If Boo Then
  82.         MsgBox "自检成功,有机会得分,具体还要看实际结果, 效率指数:" & Index
  83.     Else
  84.         MsgBox "自检有错误,不得分" & "  效率指数:" & Index
  85.     End If
  86. End Sub
复制代码
答题后 请运行 自检 程序

答题者请跟帖占位,跟帖中不要出现与题目相关的内容,否则不予评分。
截止日期 2009-10-20 以发邮件时间为准。
答案请按如下格式发送到邮箱 26258103@163.com (不需要附件,纯文字即可)
邮件主题: VBA53期国庆附加题答案
邮件内容:

  1. 'ID :  xxxxxxxxxxxxxxxx
  2. Function N2ChrX(ByVal L As Long, ByVal N As Integer) As String
  3.     '作用:将Long值转换为 N 进制所表示的字符串
  4.     '参数说明 L 要转换的值, N (2-36) 将要使用的进制数
  5.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  6. End Function
  7. Function ChrX2N(ByVal S As String, ByVal N As Integer) As Long
  8.     '作用:字符串值转换为 N 进制所表示的字符串
  9.     '参数说明 S 要转换的N进制字符串, N (2-36) 对S变量进制数的说明
  10.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  11.     S = UCase(S)
  12.    
  13. End Function




复制代码
参考答案:

  1. 'ID : LDY
  2. Function N2ChrX(ByVal L As Long, N As Integer) As String
  3.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  4.     Dim v As Double, x As Double, y As Long
  5.     If N = 10 Then N2ChrX = L: Exit Function' 10进制转10进制没必要处理,直接赋值
  6.     v = L - (L < 0) * 4294967296#  '把负数转为 正数 赋值给 Double
  7.     Do
  8.         N2ChrX = Mid(Jzs, v - Int(v / N) * N + 1, 1) & N2ChrX
  9.         v = Int(v / N)
  10.     Loop While v > 0
  11. End Function

  12. Function ChrX2N(ByVal S As String, N As Integer) As Long
  13.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  14.     Dim i%, v As Double
  15.     S = UCase(S)
  16.     If N = 10 Then ChrX2N = S: Exit Function
  17.     For i = 1 To Len(S)
  18.         v = v + (InStr(Jzs, Mid$(S, i, 1)) - 1) * N ^ (Len(S) - i)
  19.     Next
  20.     ChrX2N = v + (v > 2147483647) * 4294967296#   
  21. End Function
复制代码


结贴 http://club.excelhome.net/viewthread.php?tid=484032&page=4#pid3244334

[ 本帖最后由 ldy 于 2009-10-22 15:13 编辑 ]

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2009-9-23 01:10 | 显示全部楼层
邮件已发送,请查收,多谢!!

俺用的方法不好



  1. '论坛ID:HHAAMM    OK + 2
  2. Function N2ChrX(ByVal L As Long, ByVal N As Integer) As String
  3.     '作用:将Long值转换为 N 进制所表示的字符串
  4.     '参数说明 L 要转换的值, N (2-36) 将要使用的进制数
  5.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  6.     Dim m As Double, i%, j%, p$, b As Double, LL As Double
  7.     Dim a(100) As Double
  8.     LL = L
  9.     If LL < 0 Then
  10.         Dim x1 As Double, i1 As Integer, t%
  11.         Dim bb(31) As Integer
  12.         x1 = Abs(LL / 2)
  13.         dInt = Abs(Int(x1))
  14.         t1 = 31
  15.         If InStr(x1, ".") Then bb(t1) = 1 Else bb(t1) = 0
  16.         Do While dInt > 0
  17.             t1 = t1 - 1
  18.             x1 = dInt / 2
  19.             dInt = Int(x1)
  20.             If InStr(x1, ".") Then bb(t1) = 1 Else bb(t1) = 0
  21.         Loop
  22.         bb(0) = 1
  23.         For i1 = 1 To 31
  24.             If bb(i1) = 1 Then bb(i1) = 0 Else bb(i1) = 1
  25.         Next
  26.         For i1 = 31 To 1 Step -1
  27.             If bb(i1) = 1 Then bb(i1) = 0 Else bb(i1) = 1: Exit For
  28.         Next
  29.         x1 = 0
  30.         For i1 = 31 To 0 Step -1
  31.             x1 = x1 + bb(i1) * 2 ^ (31 - i1)
  32.         Next
  33.         LL = x1
  34.     End If
  35.     i = 100
  36.     Do
  37.         b = Int(LL / (N - 0.00000000001))
  38.         If LL >= N Then
  39.             a(i) = (LL - b * N)
  40.         Else
  41.             a(i) = LL
  42.             Exit Do
  43.         End If
  44.         LL = b
  45.         i = i - 1
  46.     Loop
  47.    
  48.     For i = 0 To 100
  49.         If a(i) > 0 Then Exit For
  50.     Next
  51.     For j = i To 100
  52.         p = Mid(Jzs, a(j) + 1, 1)
  53.         N2ChrX = N2ChrX & p
  54.     Next
  55. End Function
  56. Function ChrX2N(ByVal S As String, ByVal N As Integer) As Long
  57.     '作用:字符串值转换为 N 进制所表示的字符串
  58.     '参数说明 S 要转换的N进制字符串, N (2-36) 对S变量进制数的说明
  59.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  60.     S = UCase(S)
  61.     Dim a() As Byte, m As Double, i%, j%, t%
  62.     a = S
  63.     j = UBound(a)
  64.     t = (UBound(a) + 1) / 2 - 1
  65.     For i = 0 To j Step 2
  66.         If a(i) < 64 Then
  67.             m = m + (a(i) - 48) * N ^ t
  68.             t = t - 1
  69.         Else
  70.             m = m + (a(i) - 55) * N ^ t
  71.             t = t - 1
  72.         End If
  73.     Next
  74.     If m > 2147483647 Then ChrX2N = m - 4294967296# Else ChrX2N = m
  75. End Function
复制代码

[ 本帖最后由 ldy 于 2009-10-21 17:28 编辑 ]

本帖子中包含更多资源

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

x

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2009-9-23 07:00 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2009-9-23 08:01 | 显示全部楼层
个人理解哦

lz表示的N进制规定用常量中的字母哦
比如如果我要求将10进制转换为10进制,而这10进制用中文表示(一以已亿意易依伊亦咦)

这是不也是一种方式捏
-----------------------------------------------------------------------------------------------------------------------
按照lz斑竹所表示的常量范围,应该仅限于36进制内的了。如果出现37,打他PP
-----------------------------------------------------------------------------------------------------------------------
个人理解,不知当否。还请lz斑竹明示,以利答题

[ 本帖最后由 biaotiger1 于 2009-9-23 08:04 编辑 ]

TA的精华主题

TA的得分主题

发表于 2009-9-23 10:22 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2009-9-23 10:24 | 显示全部楼层
原帖由 泓() 于 2009-9-23 08:06 发表
题还没做,先站位!!
与2楼同感 十六进制按你的常量(常量作什么用的?) 换算后如32=1G 而Hex(32)=20  两值不相同
你的2-36进制是否改变了原来进制如Hex等应该有的值

还是给出你的验证答案比较适当
比如 65 ...

正数相对简单些,负数我不会
一堆的数,看着就迷糊

TA的精华主题

TA的得分主题

 楼主| 发表于 2009-9-23 12:25 | 显示全部楼层
dim L as long,N As Integer
L = -1
N = 19 ' 限 2 到36
msgbox  N2ChrX(L,8)  = Oct(L)
msgbox  N2ChrX(L,16)  = Hex(L)
msgbox  N2ChrX(L,10)  = Cstr(L)
msgbox  ChrX2N(Hex(L),16)  = L
msgbox  ChrX2N(Oct(L),8)  = L
msgbox  ChrX2N(Cstr(L),10)  = L
msgbox  ChrX2N(N2ChrX(L,N),N) =L

不管 L = 什么长整数 ,上面7 个消息框 都应该显示 TRUE
8 和 16进制 可以用VBA自带函数检验,至于其他进制,给几个边界值参考下。

HEX 和 OCT 是如何处理 负数的,你的代码也要按照此规律编写。
只要你编写的函数中不使用 Hex  和 Oct 函数,而
msgbox  N2ChrX(L,8)  = Oct(L)
msgbox  N2ChrX(L,16)  = Hex(L)
上面这两个等式成立,其他的进制转换自然迎刃而解。

0             = 17进制字符串 "0"
1             = 17进制字符串 "1"
10            = 17进制字符串 "A"
-1             = 17进制字符串 "A7FFDA90"
2147483647    = 17进制字符串 "53G7F548"
-2147483648    = 17进制字符串 "53G7F549"

0             = 18进制字符串 "0"
1             = 18进制字符串 "1"
10            = 18进制字符串 "A"
-1             = 18进制字符串 "704HE7G3"
2147483647    = 18进制字符串 "3928G3H1"
-2147483648    = 18进制字符串 "3928G3H2"

0             = 11进制字符串 "0"
1             = 11进制字符串 "1"
10            = 11进制字符串 "A"
-1             = 11进制字符串 "1904440553"
2147483647    = 11进制字符串 "A02220281"
-2147483648    = 11进制字符串 "A02220282"

0             = 9进制字符串 "0"
1             = 9进制字符串 "1"
10            = 9进制字符串 "11"
-1             = 9进制字符串 "12068657453"
2147483647    = 9进制字符串 "5478773671"
-2147483648    = 9进制字符串 "5478773672"

0             = 4进制字符串 "0"
1             = 4进制字符串 "1"
10            = 4进制字符串 "22"
-1             = 4进制字符串 "3333333333333333"
2147483647    = 4进制字符串 "1333333333333333"
-2147483648    = 4进制字符串 "2000000000000000"

0             = 16进制字符串 "0"
1             = 16进制字符串 "1"
10            = 16进制字符串 "A"
-1             = 16进制字符串 "FFFFFFFF"
2147483647    = 16进制字符串 "7FFFFFFF"
-2147483648    = 16进制字符串 "80000000"

0             = 36进制字符串 "0"
1             = 36进制字符串 "1"
10            = 36进制字符串 "A"
-1             = 36进制字符串 "1Z141Z3"
2147483647    = 36进制字符串 "ZIK0ZJ"
-2147483648    = 36进制字符串 "ZIK0ZK"

TA的精华主题

TA的得分主题

 楼主| 发表于 2009-9-23 12:29 | 显示全部楼层
[quote]原帖由 biaotiger1 于 2009-9-23 08:01 发表
个人理解哦

lz表示的N进制规定用常量中的字母哦
比如如果我要求将10进制转换为10进制,而这10进制用中文表示(一以已亿意易依伊亦咦)

这是不也是一种方式捏
--------------------------------------------- ... [/quote]


10 进制转换 10进制,无变化,不用转换,直接函数内赋值就行了。
其他理解正确。
本来想加一些中文在常量中,弄个500进制的,考虑到繁体简体的问题不便验证,就只用36个数字和英文字母了。
其实道理是一样的,这道题如果作对了,只要增加常量的字符数,2000进制也没问题。

TA的精华主题

TA的得分主题

发表于 2009-9-23 13:35 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
16进制没有1G,因为用的字符只能到F。
负数的表示跟总位数有关,这里应该是不考虑的吧。
其实还有个小数的问题,比负数复杂一些。

邮件已发,请查收。

[ 本帖最后由 jmouse 于 2009-9-23 13:46 编辑 ]



收到 ,负数也要考虑的。在 8楼 有说明——ldy

TA的精华主题

TA的得分主题

发表于 2009-9-23 16:01 | 显示全部楼层
呃,没有注意到8楼有关负数的说明。
已经重发邮件,请查收。


收到 -ldy

  1. '论坛ID: jmouse OK +2
  2. Function N2ChrX(ByVal L As Long, ByVal N As Integer) As String
  3.     '作用:将Long值转换为 N 进制所表示的字符串
  4.     '参数说明 L 要转换的值, N (2-36) 将要使用的进制数
  5.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  6.     If N = 10 Then
  7.         N2ChrX = L
  8.     Else
  9.         If L < 0 Then
  10.             x = Int((2 ^ 32 + L) / N)
  11.             m = 2 ^ 32 + L - x * N
  12.             N2ChrX = Mid(Jzs, m + 1, 1) + N2ChrX
  13.             L = x
  14.         End If
  15.         While L >= N
  16.             m = L - Int((L / N)) * N
  17.             N2ChrX = Mid(Jzs, m + 1, 1) + N2ChrX
  18.             L = Int((L / N))
  19.         Wend
  20.         N2ChrX = Mid(Jzs, L + 1, 1) + N2ChrX
  21.     End If
  22. End Function
  23. Function ChrX2N(ByVal s As String, ByVal N As Integer) As Long
  24.     '作用:字符串值转换为 N 进制所表示的字符串
  25.     '参数说明 S 要转换的N进制字符串, N (2-36) 对S变量进制数的说明
  26.     Const Jzs As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  27.     s = UCase(s)
  28.     If N = 10 Then
  29.         ChrX2N = s
  30.     Else
  31.         i = 1
  32.         Dim tmp As Double
  33.         While s <> ""
  34.             tmp = (InStr(1, Jzs, Right(s, 1)) - 1) * i + tmp
  35.             s = Left(s, Len(s) - 1)
  36.             i = i * N
  37.         Wend
  38.         If tmp > 2147483647 Then
  39.             ChrX2N = tmp - 2 ^ 32
  40.         Else
  41.             ChrX2N = tmp
  42.         End If
  43.     End If
  44. End Function
复制代码

[ 本帖最后由 ldy 于 2009-10-21 17:27 编辑 ]

评分

1

查看全部评分

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

本版积分规则

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

GMT+8, 2024-4-16 23:07 , Processed in 0.048358 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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