Microsoft技术社区联盟成员,全球领先的Excel2003/2007/2010门户,Office培训学习的最佳社区
设为首页收藏本站|繁體中文 切换到窄版

Excel Home论坛

 找回密码
 免费注册

用新浪微博连接

一步搞定

QQ登录

只需一步,快速开始

魔方网表,Excel终结者,永久免费 Excel服务器2010软件和教程下载 菜鸟啃Excel: 样章试读
Excel不给力? 何不试试FoxTable! 2012年Excel免费培训班2-6月开课计划 新人必读:ExcelHome最佳学习方法 免费下载Excel行业应用视频教程
精粹:成为Excel高手的捷径 免费下载39集新Excel精粹视频教程 免费学习Excel数据透视表视频教程 入门必看《循序渐进学Excel》视频
Excel辅助工具的巅峰之作--Kutools 免费学习Excel 2007精粹视频教程 Office Tab,Office界面的革命性创新 搞不定老板要的报表?我们来帮您
  • 3552财富
  • 0鲜花
  • 65技术
  • 积分排行
    144
    帖子
    2116
    精华
    1
    分享
    0

    [求助]一个计算质数的小程序,请高手优化一下。 [复制链接]

    因为在别的程序中需要质数,所以写了一个计算一定范围内质数的小程序,但随着范围的扩大(如5万),速度越来越慢了,请高手优化一下。

     


    附件: 你需要登录才可以下载或查看附件。没有帐号?免费注册
  • 7694财富
  • 11鲜花
  • 81技术
  • 积分排行
    78
    帖子
    3681
    精华
    3
    分享
    0
    发表于 2006-6-23 00:29:24 |显示全部楼层
    纯数学的东西基本上没用过,在你的基础上改的,供参考.
     Sub aTest()
        Dim m&, n&, k&, a&, b&, arr(), t1
        t1 = Timer
        ReDim arr(1 To 65536)
        k = 1
        Range("D2:D" & Range("D65536").End(xlUp).Row + 1).Clear
        For a = 2 To [a2]
            n = a \ 2
            For b = 2 To n
                If a Mod b = 0 Then Exit For
            Next b
            If b > n Then
                arr(k) = a
                k = k + 1
            End If
        Next a
        ReDim Preserve arr(1 To k - 1)
        Range("D2:D" & k) = Application.Transpose(arr)
        Debug.Print Timer - t1
    End Sub
    无论你走得多么远,你的心总和我连在一起; 无论黄昏时树的影子有多长,它总是和树根连在一起。 穿别人的鞋,走自己的路,让他找去吧!
  • 7694财富
  • 11鲜花
  • 81技术
  • 积分排行
    78
    帖子
    3681
    精华
    3
    分享
    0
    发表于 2006-6-23 00:39:18 |显示全部楼层
    凭感觉2楼的算法不会是最优的,应该还有更快的方法.
    时间太晚,有时间查查质数的算法看看.
    欢迎有兴趣的朋友参与.
    无论你走得多么远,你的心总和我连在一起; 无论黄昏时树的影子有多长,它总是和树根连在一起。 穿别人的鞋,走自己的路,让他找去吧!
  • 3337财富
  • 0鲜花
  • 12技术
  • 积分排行
    358
    帖子
    1558
    精华
    1
    分享
    0
    发表于 2006-6-23 02:35:27 |显示全部楼层

    Private Declare Function timeGetTime Lib "winmm.dll" () As Long


    ' ---Test1

    Sub aTest()
        Dim m&, n&, k&, a&, b&, arr(), t1
        t1 = timeGetTime
        ReDim arr(1 To 65536)
        k = 1
        Range("D2:D" & Range("D65536").End(xlUp).Row + 1).Clear
        For a = 2 To [A2]
            n = a \ 2
            For b = 2 To n
                If a Mod b = 0 Then Exit For
            Next b
            If b > n Then
                arr(k) = a
                k = k + 1
            End If
        Next a
        ReDim Preserve arr(1 To k - 1)
        Range("D2:D" & k) = Application.Transpose(arr)
        Debug.Print timeGetTime - t1 & "ms"
    End Sub

    '--- Test 2

    Sub Emily_230606()
        Dim m&, n&, k&, a&, b&, arr(), t1
        t1 = timeGetTime
        ReDim arr(1 To 65536)
        k = 2
        arr(1) = 2

        Range("E2:E" & Range("E65536").End(xlUp).Row + 1).Clear
        For a = 3 To [A2]
            If IsPrime(a) Then
                arr(k) = a
                k = k + 1
            End If
        Next a
        ReDim Preserve arr(1 To k - 1)
        Range("E2:E" & k) = Application.Transpose(arr)
        Debug.Print timeGetTime - t1 & "ms"
    End Sub

    '

    Function IsPrime(TestNumber As Long) As Boolean
    Dim Count As Long
    Dim Half As Long
    If (TestNumber Mod 2) = 0 Then
             Exit Function
     End If
     Half = Sqr(TestNumber)
     For Count = 3 To Half Step 2
         If (TestNumber Mod Count) = 0 Then
             Exit Function
         End If
     Next
     IsPrime = True
    End Function
    '

    '

    ' A1 = 100000

    ' P3  800MHz

    Test1 ---> 42852ms

    Test2 ---> 470ms

    Have no passion for Excel especially at   "Home"
  • 3552财富
  • 0鲜花
  • 65技术
  • 积分排行
    144
    帖子
    2116
    精华
    1
    分享
    0
    发表于 2006-6-23 08:29:48 |显示全部楼层

    谢谢用兄及lotustower女士的关注及解答

    lotustower女士的方法真是让人大开眼界,a2=600000 时不到5秒完成,用我的程序不知道计算到何月何日。其中解法得慢慢领会。

  • 29419财富
  • 63鲜花
  • 63技术
  • 积分排行
    15
    帖子
    12283
    精华
    1
    分享
    0
    发表于 2006-6-23 08:42:09 |显示全部楼层
    Sub getprime()
    Dim max As Long, arr, i As Long, k As Long, beprime As Boolean, t As Single
    t = Timer
    max = CLng(InputBox("please enter an integer", , 500000))
    ReDim arr(1 To max)
    arr(1) = 2
    arr(2) = 3
    i = 5
    k = 2
    While i <= max
    beprime = True
    j = 2
    Do While j <= Sqr(i)
    If i Mod arr(j) = 0 Then beprime = False: Exit Do
    j = j + 1
    Loop
    If beprime = True Then
    k = k + 1
    arr(k) = i
    End If
    i = i + 2
    Wend
    ReDim Preserve arr(1 To k)
    Range("c2").Resize(k, 1) = WorksheetFunction.Transpose(arr)
    MsgBox "在1--" & max & "内找到" & k & "个质数", vbInformation, "用时" & Timer - t & "秒"
    End Sub
  • 29419财富
  • 63鲜花
  • 63技术
  • 积分排行
    15
    帖子
    12283
    精华
    1
    分享
    0
    发表于 2006-6-23 08:49:43 |显示全部楼层

    1. 只在奇数内循环

    2. 利用已有的质数

    3. 循环到该数字的平方根即可.

    其实,递归可能更快,例如:

    查询1000000内所有质数,先算出1000内的质数,再看1001-1000000内的奇数能否被1000内的质数整除.

    再查询1000内质数,先算出33内的质数,再看35-1000内的奇数能否被33内的质数整除.

    再查询33内质数,先算出5内的质数,再看7-33内的奇数能否被5内的质数整除.

  • 3818财富
  • 0鲜花
  • 21技术
    • 等级 6EH能手
    积分排行
    236
    帖子
    2092
    精华
    3
    分享
    0
    发表于 2006-6-23 08:55:37 |显示全部楼层

    判断质数的唯一方法就是用从2开始的由小到大的所有质数去试除它。

    如果有人能找到比这个更高效的方法那他会成为全世界最伟大的数学家!

    呵呵!也就是说那是不可能的。

  • 3552财富
  • 0鲜花
  • 65技术
  • 积分排行
    144
    帖子
    2116
    精华
    1
    分享
    0
    发表于 2006-6-23 09:22:12 |显示全部楼层

    哇,真是百花齐放,各有各的高招。

    谢谢northwolves兄解释算法原理。

    经测试,还是lotustower的最快!

  • 29419财富
  • 63鲜花
  • 63技术
  • 积分排行
    15
    帖子
    12283
    精华
    1
    分享
    0
    发表于 2006-6-23 10:53:21 |显示全部楼层

     优化一下:

    Sub getprime()
    Dim arr, t As Single, n As Long
    t = Timer
    MAX = CLng(InputBox("please enter an integer", , 800000))
    primen MAX, arr
    n = UBound(arr)
    Range("a1").Resize(n, 1) = WorksheetFunction.Transpose(arr)
    MsgBox "在1--" & MAX & "内找到" & n & "个质数", vbInformation, "用时" & Timer - t & "秒"
    End Sub


    Sub primen(ByVal MAX As Long, ByRef p)
    Dim i As Long, j As Long, k As Long, temp, s As Long, n As Long, beprime As Boolean
    If MAX = 2 Then
    ReDim p(1 To 1)
    p(1) = 2
    ElseIf MAX = 3 Then
    ReDim p(1 To 2)
    p(1) = 2
    p(2) = 3
    End If
    If MAX > 4 Then
    s = Int(Sqr(MAX))
    primen s, temp
    n = UBound(temp)
    p = temp
    k = n
    For i = s To MAX
    beprime = True
    If i Mod 6 = 1 Or i Mod 6 = 5 Then
    For j = 2 To n
    If i Mod temp(j) = 0 Then beprime = False: Exit For
    Next
    If beprime = True Then
    k = k + 1
    ReDim Preserve p(1 To k)
    p(k) = i
    End If
    End If
    Next
    End If
    End Sub

    发表回复

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

    发帖时请遵守我国法律,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任。
    回顶部