素数的快速列举(三)
在http://blog.csdn.net/northwolves/archive/2005/11/18/532695.aspx 文章中,对小素数的列举进行了探讨,今天发现,由于小素数的倍数比较多,过滤所用时间较长。所以先对奇数进行初步过滤,可以达到提速的效果,继续改进如下:
Private Sub Command1_Click()
Dim p() As Long
Dim i As Long
For i = 2 To 8
prime 10 ^ i, p
Next
End Sub
Sub prime(ByVal n As Long, ByRef prime() As Long)
ReDim prime(5761495) '10^8以内的素数个数
Dim i As Long, temp As Long, half As Long, p As Long, pcount As Long, mytime As Long, msg As String
mytime = Timer '计时
'把所有素数分成49种情况 210n+1,210n+11,210n+13,210n+17,210n+19,210n+23,210n+29,210n+31,210n+37,210n+41,210n+43,210n+47,210n+53,210n+59,210n+61,210n+67,210n+71,210n+73,210n+79,210n+83,210n+89,210n+97,210n+101,210n+103,210n+107,210n+109,210n+113,210n+121,210n+127,210n+131,210n+137,210n+139,210n+143,210n+149,210n+151,210n+157,210n+163,210n+167,210n+169,210n+173,210n+179,210n+181,210n+187,210n+191,210n+193,210n+197,210n+199,210n+209,210n+211
Dim a(1 To 209) As Byte
a(1) = 10
a(11) = 2
a(13) = 4
a(17) = 2
a(19) = 4
a(23) = 6
a(29) = 2
a(31) = 6
a(37) = 4
a(41) = 2
a(43) = 4
a(47) = 6
a(53) = 6
a(59) = 2
a(61) = 6
a(67) = 4
a(71) = 2
a(73) = 6
a(79) = 4
a(83) = 6
a(89) = 8
a(97) = 4
a(101) = 2
a(103) = 4
a(107) = 2
a(109) = 4
a(113) = 8
a(121) = 6
a(127) = 4
a(131) = 6
a(137) = 2
a(139) = 4
a(143) = 6
a(149) = 2
a(151) = 6
a(157) = 6
a(163) = 4
a(167) = 2
a(169) = 4
a(173) = 6
a(179) = 2
a(181) = 6
a(187) = 4
a(191) = 2
a(193) = 4
a(197) = 2
a(199) = 10
a(209) = 2
Dim x() As Byte
ReDim x(1 To n)
'the first 10 prime
prime(0) = 2
prime(1) = 3
prime(2) = 5
prime(3) = 7
prime(4) = 11
prime(5) = 13
prime(6) = 17
prime(7) = 19
prime(8) = 23
prime(9) = 29
pcount = 9
p = 11
Do While p * p <= n
temp = p * p
For i = temp To n Step 2 * p 'p的倍数
x(i) = 1 '设为1表示弃去
Next
again:
p = p + a(p Mod 210)
If x(p) = 1 Then GoTo again
Loop
i = 31
Do While i < n
If x(i) = 0 Then
pcount = pcount + 1
prime(pcount) = i '赋值
End If
i = i + a(i Mod 210)
Loop
ReDim Preserve prime(pcount) '重设置数组大小节省空间
msg = Format(Timer - mytime, "0.0000") & " seconds."
Debug.Print "n=" & n & ",prime count=" & pcount + 1 & ", The calulating time is " & msg
End Sub
返回:
n=1000,prime count=168, The calulating time is 0.011 seconds.
n=10000,prime count=1229, The calulating time is 0.031 seconds.
n=100000,prime count=9592, The calulating time is 0.072 seconds.
n=1000000,prime count=78498, The calulating time is 0.1033 seconds.
n=10000000,prime count=664579, The calulating time is 0.7756 seconds.
n=100000000,prime count=5761455, The calulating time is 11.0334 seconds.
可以看到,筛选10000000内所有素数并赋值到一个数组,仅仅需要0.77秒钟,速度大大提高。