Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
楼主: yslvictor

[已解决]请教老师,有没有更快的速度运行下列程序的代码

[复制链接]
发表于 2014-11-21 19:12 | 显示全部楼层
香川群子 发表于 2014-11-21 16:44
不考虑输出到工作表的时间,5万行计算比较运算只要0.05秒。

谢谢群子老师!

学习了!!{:021:}
回复

使用道具 举报

 楼主| 发表于 2014-11-22 00:58 | 显示全部楼层
谢谢各位论坛老师,这些代码都非常的好,用这些代码时,同时把F列的格式变成文本格式,输出时间提高不少。谢谢。
回复

使用道具 举报

发表于 2014-11-22 14:45 | 显示全部楼层
grf1973 发表于 2014-11-21 16:00
如果数据量再大一点,个人觉得第3种方法可能最快

很规律的数字,应该直接用数组计算和记录,不要用字典……速度会相差数倍!

下面代码算法目前速度最快!
  1. Sub test1()
  2.     Dim a$(9), b$(999), i&, i1&, i2&, i3&, s$
  3.     For i = 0 To 9 Step 2
  4.         a(i) = "偶"
  5.         a(i + 1) = "奇"
  6.     Next
  7.     s = "偶偶偶"
  8.     For i1 = 0 To 9
  9.       Mid(s, 1, 1) = a(i1)
  10.     For i2 = 0 To 9
  11.       Mid(s, 2, 1) = a(i2)
  12.     For i3 = 0 To 9
  13.       Mid(s, 3, 1) = a(i3)
  14.       b(i1 * 100 + i2 * 10 + i3) = s
  15.     Next i3, i2, i1
  16.     [a1].Resize(1000) = WorksheetFunction.Transpose(b)
  17. End Sub
复制代码
优点:
① 全程使用数组 而无需使用字典
     用a$(9) 记录0-9这10个数字对应的奇偶类型
     用b$(999) 记录000-9999这1000个数值对应的奇偶类型

② 直接步长=2循环生成a数组结果,不需要使用Mod 2计算奇偶性。

③ 用0 To 9的3层循环直接生成000-999数值的百位十位个位,速度更快!
    用 b(i1 * 100 + i2 * 10 + i3) 来还原3位数值

④ 用Mid函数置换更新s字符串结果,比文本字符串反复拼接的速度要快很多!


呵呵。
回复

使用道具 举报

发表于 2014-11-22 14:55 | 显示全部楼层
而下面直接拼接的算法,速度要慢一些,大约慢1/3 即 66.7%
  1. Sub test2()
  2.     Dim a$(9), b$(999), i&, i1&, i2&, i3&
  3.     For i = 0 To 9 Step 2
  4.         a(i) = "偶"
  5.         a(i + 1) = "奇"
  6.     Next
  7.     For i1 = 0 To 9
  8.     For i2 = 0 To 9
  9.     For i3 = 0 To 9
  10.       b(i1 * 100 + i2 * 10 + i3) = a(i1) & a(i2) & a(i3)
  11.     Next i3, i2, i1
  12. '    [a1].Resize(1000) = WorksheetFunction.Transpose(b)
  13. End Sub
复制代码
回复

使用道具 举报

发表于 2014-11-22 14:56 | 显示全部楼层
而如果不采用3层循环,而是直接000-999循环+字符串拼接,速度也一样的要慢大约1/3 即66.7%
  1. Sub test3()
  2.     Dim a$(9), b$(999), i&
  3.     For i = 0 To 9 Step 2
  4.         a(i) = "偶"
  5.         a(i + 1) = "奇"
  6.     Next
  7.     For i = 0 To 999
  8.         b(i) = a(i \ 100) & a(i \ 10 Mod 10) & a(i Mod 10)
  9.     Next
  10.     [a1].Resize(1000) = WorksheetFunction.Transpose(b)
  11. End Sub
复制代码
回复

使用道具 举报

发表于 2014-11-22 15:03 | 显示全部楼层
我原来的算法速度也很快……而且是通用算法,即只要改变位数n就可以得到相应的奇偶性判断结果。
  1. Sub test() 'by kagawa 2014/11/21
  2.     Dim i&, j&, k&, n&, s$, s1$, s2$, tms#
  3.     tms = Timer
  4.    
  5.     n = 3 '可以任意定义位数n
  6.     ReDim a&(1 To n)
  7.     s1 = "奇" 'ChrW(22855)
  8.     s2 = "偶" 'ChrW(20598)
  9.     s = String(n, s2)
  10.    
  11.     k = 10 ^ n - 1: ReDim b$(k): b(0) = s
  12.     For i = 1 To k
  13.         For j = n To 1 Step -1
  14.             If a(j) = 9 Then
  15.                 a(j) = 0
  16.                 Mid(s, j, 1) = s2
  17.             Else
  18.                 a(j) = a(j) + 1
  19.                 If a(j) Mod 2 Then Mid(s, j, 1) = s1 Else Mid(s, j, 1) = s2
  20.                 Exit For
  21.             End If
  22.         Next
  23.         b(i) = s
  24.     Next
  25.     [b1].Resize(10 ^ n) = WorksheetFunction.Transpose(b)
  26. End Sub
复制代码
代码比较复杂一点,所以耗时也略有增加……大约慢 20%
但是,能够任意设置n位数,这个是我这个代码的特点。
回复

使用道具 举报

发表于 2014-11-22 15:11 | 显示全部楼层
grf1973 发表于 2014-11-21 16:00
如果数据量再大一点,个人觉得第3种方法可能最快

你的第3种方法用了字典……速度反而更慢,比我的最快代码要慢20倍!
  1. Sub test3()
  2.     Dim d, d1, i&, t1&, t2&, t3&
  3.     Set d = CreateObject("scripting.dictionary")
  4.     Set d1 = CreateObject("scripting.dictionary")
  5.     For i = 0 To 9:  d(i) = IIf(i Mod 2, "奇", "偶"): Next
  6.     For i = 0 To 999
  7.         t1 = i \ 100: t2 = (i - t1 * 100) \ 10: t3 = Val(Right(i, 1))
  8.         d1(i) = d(t1) & d(t2) & d(t3)
  9.     Next
  10.     [a1].Resize(1000) = WorksheetFunction.Transpose(d1.items)
  11. End Sub
复制代码
回复

使用道具 举报

发表于 2014-11-22 15:12 | 显示全部楼层
香川群子 发表于 2014-11-22 14:45
很规律的数字,应该直接用数组计算和记录,不要用字典……速度会相差数倍!

下面代码算法目前速度最快 ...

Sub test2()
    Dim a$(9), b$(999), i&, i1&, i2&, i3&, s$, j
    For i = 0 To 9 Step 2
        a(i) = "偶"
        a(i + 1) = "奇"
    Next
    s = "偶偶偶"
    For i1 = 0 To 9
        Mid(s, 1, 1) = a(i1)
        
        For i2 = 0 To 9
            Mid(s, 2, 1) = a(i2)
            
            For i3 = 0 To 9
                Mid(s, 3, 1) = a(i3)
                b(j) = s
                j = j + 1
            Next i3
        Next i2
    Next i1
    [a1].Resize(1000) = WorksheetFunction.Transpose(b)
End Sub

谢谢群子老师,学习了!
为什么不用j替换下呀?不过好像差异太小,只不过好看清些。
回复

使用道具 举报

发表于 2014-11-22 15:19 | 显示全部楼层
本帖最后由 香川群子 于 2014-11-22 15:26 编辑
爱疯 发表于 2014-11-22 15:12
Sub test2()
    Dim a$(9), b$(999), i&, i1&, i2&, i3&, s$, j
    For i = 0 To 9 Step 2

再介绍一种有趣的算法思路:
  1. Sub test4() 'by kagawa 2014/11/22
  2.     Dim arr, i&, i1&, i2&, i3&, j&, k&, n&, r&, s$, s1$, s2$, tms#
  3.     tms = Timer
  4.    
  5.     n = 3: ReDim a&(1 To n)
  6.     s1 = ChrW(22855) '"奇"
  7.     s2 = ChrW(20598) '"偶"
  8.     s = String(n, s2)
  9.     ReDim b$(2 ^ n - 1)
  10.     For i1 = 1 To 0 Step -1
  11.       Mid(s, 1, 1) = IIf(i1 Mod 2, s1, s2)
  12.     For i2 = 1 To 0 Step -1
  13.       Mid(s, 2, 1) = IIf(i2 Mod 2, s1, s2)
  14.     For i3 = 1 To 0 Step -1
  15.       Mid(s, 3, 1) = IIf(i3 Mod 2, s1, s2)
  16.         i = i1 * 4 + i2 * 2 + i3
  17.         b(i) = s
  18.     Next i3, i2, i1
  19. '    Exit Sub
  20.    
  21.     k = 10 ^ n - 1: ReDim c$(k): c(0) = b(0)
  22.     For i = 1 To k
  23.         For j = n To 1 Step -1
  24.             If a(j) = 9 Then
  25.                 a(j) = 0
  26.                 r = r - 2 ^ (n - j)
  27.             Else
  28.                 a(j) = a(j) + 1
  29.                 If a(j) Mod 2 Then r = r + 2 ^ (n - j) Else r = r - 2 ^ (n - j)
  30.                 Exit For
  31.             End If
  32.         Next
  33.         c(i) = b(r)
  34.     Next
  35.     [a1].Resize(10 ^ n) = WorksheetFunction.Transpose(c)
  36. End Sub
复制代码
首先生成0-7这8种不同的奇偶类型对应字符,(二进制3位数的不同组合数=2^3-1=8-1=7)

然后计算每一个n位数 i 数值对应的奇偶换算值。

本代码和前面5楼第1段代码一开始的用法类似。但实现方法不同。

遗憾的是、速度并未提高。呵呵。
回复

使用道具 举报

发表于 2014-11-22 15:48 | 显示全部楼层
本帖最后由 香川群子 于 2014-11-22 15:49 编辑

如果不考虑通用性,固定n=3位,则上述算法的代码可以提高速度如下:
  1. Sub test2() 'by kagawa 2014/11/22
  2.     Dim i&, i1&, i2&, i3&, s$, s1$, s2$
  3.    
  4.     Dim a&(9), b$(1, 1, 1), c$(999)
  5.     For i = 1 To 9 Step 2
  6.         a(i) = 1
  7.     Next
  8.     s = "偶偶偶"
  9.     For i1 = 0 To 1
  10.       Mid(s, 1, 1) = IIf(i1, "奇", "偶")
  11.     For i2 = 0 To 1
  12.       Mid(s, 2, 1) = IIf(i2, "奇", "偶")
  13.     For i3 = 0 To 1
  14.       Mid(s, 3, 1) = IIf(i3, "奇", "偶")
  15.       b(i1, i2, i3) = s
  16.     Next i3, i2, i1

  17.     i = 0
  18.     For i1 = 0 To 9
  19.     For i2 = 0 To 9
  20.     For i3 = 0 To 9
  21.         c(i) = b(a(i1), a(i2), a(i3)): i = i + 1
  22.     Next i3, i2, i1
  23.     [c1].Resize(1000) = WorksheetFunction.Transpose(c)
  24. End Sub
复制代码
首先、生成8种奇偶类型,然后直接3层循环得到结果……免去所有Mod计算。
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-27 19:13 , Processed in 0.325358 second(s), 8 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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