Sub 查找素数()
Dim i&, j&, k&, m&, n&
n = 100000
m = Int((n - 1) / 2): ReDim a(1 To m) As Byte
For i = 1 To Sqr(n) \ 2
If a(i) = 0 Then
For j = i * 3 + 1 To m Step i * 2 + 1
a(j) = 1
Next
End If
Next
ReDim b&(1 To m): b(1) = 2: k = 1 '当a(i)=0时,2i+1是质数
For i = 1 To m
If a(i) = 0 Then k = k + 1: b(k) = i * 2 + 1
Next
ReDim Preserve b&(1 To k)
[a1].Resize(k) = Application.Transpose(b)
End Sub
算法:
① 仅需检查<Sqr(N)的奇素数 s= i * 2 + 1 ( i 从1开始,即3、5、7、11……)
② 从奇数数组的 i * 3 + 1 位置开始按步长s,用筛子算法检查。
注意,该奇数数组中位置换算成实际数字位置为:(i*3+1)*2+1=i*6+3
即对于i=1 的实际奇数=i*2+1=3来说,起始位置是从=i*6+3=9开始。
(检查时也跳过所有偶数倍的素数)
因此奇数数组检查时的步长s=i*2+1=3 换算成实际数值的步长也会是=(i*2+1)*2=6
即,从9开始,然后 9+6=15、15+6=21、21+6=27……这样来排除。
即对于i=1 的实际奇数=i*2+1=3来说,起始位置是从=i*6+3=9开始。
(检查时也跳过所有偶数倍的素数)
因此奇数数组检查时的步长s=i*2+1=3 换算成实际数值的步长也会是=(i*2+1)*2=6
即,从9开始,然后 9+6=15、15+6=21、21+6=27……这样来排除。
如:
对于i=2 的实际奇数=i*2+1=2*2+1=5,检查起始位置是从=i*6+3=2*6+3=15开始。
检查时的步长换算成实际数值是=(i*2+1)*2=(2*2+1)*2=10
即,从15开始,然后 15+10=25、25+10=35、35+10=45……这样来排除。
对于i=2 的实际奇数=i*2+1=2*2+1=5,检查起始位置是从=i*6+3=2*6+3=15开始。
检查时的步长换算成实际数值是=(i*2+1)*2=(2*2+1)*2=10
即,从15开始,然后 15+10=25、25+10=35、35+10=45……这样来排除。
对于i=3 的实际奇数=i*2+1=3*2+1=7,检查起始位置是从=i*6+3=3*6+3=21开始。
检查时的步长换算成实际数值是=(i*2+1)*2=(3*2+1)*2=14
即,从21开始,然后 21+14=35、35+14=49、49+14=63……这样来排除。
检查时的步长换算成实际数值是=(i*2+1)*2=(3*2+1)*2=14
即,从21开始,然后 21+14=35、35+14=49、49+14=63……这样来排除。
③ 检查完成后,提取有效值存入数组。
当N数值较大时,可考虑定义较小的数组以便节约资源。