主题:[讨论]求1000000以内素数的个数的程序,比一比速度
idealguy
[专家分:110] 发布于 2011-12-19 23:23:00
[url=http://bbs.pfan.cn/post-379076.html]http://bbs.pfan.cn/post-379076.html[/url]
求1000000以内素数的个数的程序,比一比速度
回复列表 (共15个回复)
沙发
moz [专家分:37620] 发布于 2011-12-20 00:19:00
用EXCEL写了一个代码.
deflng a-z
sub moz()
T1#=timer
dim s(80000) '当然,这是随便定义的,不是有意的,可以在后面加多一个零,但在QB里面是不可以的.
T1# = Timer
s(1) = 2
s(2) = 3
s(3) = 5
s(4) = 7
k = 4
For i = 11 To 1000000 Step 2
ii = Sqr(i)
For j = 2 To k
If i Mod s(j) = 0 Then Exit For
If s(j) > ii Then Exit For
Next
If s(j) > ii Then
k = k + 1
s(k) = i
End If
Next
Debug.Print k, Timer - T1#
End Sub
板凳
idealguy [专家分:110] 发布于 2011-12-20 09:34:00
QB 里面可以改为:
dim s(1200)
......
k = k + 1
if k<1200 then s(k) = i
2楼代码经上述修改后QB测试通过,未编译运行时间约8秒。
3 楼
moz [专家分:37620] 发布于 2011-12-20 19:21:00
在QB里面,数组限制在64K以内,长整型为4,所以可以定义 s(16k)
但听你一解释,那就定义 1k 就足够了.
4 楼
idealguy [专家分:110] 发布于 2011-12-20 19:46:00
[quote]在QB里面,数组限制在64K以内,长整型为4,所以可以定义 s(16k)
但听你一解释,那就定义 1k 就足够了.[/quote]
要比 1k 多一点才行。
5 楼
moz [专家分:37620] 发布于 2011-12-20 21:17:00
sqr(1000000)=1k
其实,第169个质数是1009,所以,定义s(169)就够了.
既然要追求速度,根据已知的,单行IF比多行IF速度要快,
而且,还要减少循环体内的语句,那么再改一改,还真有点进步.
deflng a-z
Sub moz4()
Dim s(169)
T1# = Timer
s(1) = 2
s(2) = 3
s(3) = 5
s(4) = 7
k = 4
iii = 2
ii = 3
iiii = ii * ii
For i = 11 To 1000000 Step 2
For j = 2 To iii
If i Mod s(j) = 0 Then Exit For
Next
If j > iii Then
k = k + 1
If k < 170 Then s(k) = i
If i > iiii Then
iii = iii + 1
ii = s(iii)
iiii = ii * ii
End If
End If
Next
Debug.Print k, Timer - T1#
End Sub
既然已知s(169)=1009,干脆把循环体写多一遍,减少一行代码,速度应该还能有改善.
牺牲代码量,来提高速度,不知道实际应用中,会不会用得上?
deflng a-z
Sub moz5()
Dim s(169)
T1# = Timer
s(1) = 2
s(2) = 3
s(3) = 5
s(4) = 7
k = 4
iii = 2
ii = 3
iiii = ii * ii
For i = 11 To 1009 Step 2
For j = 2 To iii
If i Mod s(j) = 0 Then Exit For
Next
If j > iii Then
k = k + 1
s(k) = i
If i > iiii Then
iii = iii + 1
ii = s(iii)
iiii = ii * ii
End If
End If
Next
For i = 1011 To 1000000 Step 2
For j = 2 To iii
If i Mod s(j) = 0 Then Exit For
Next
If j > iii Then
k = k + 1
If i > iiii Then
iii = iii + 1
ii = s(iii)
iiii = ii * ii
End If
End If
Next
Debug.Print k, Timer - T1#, ii, iii
End Sub
6 楼
moz [专家分:37620] 发布于 2011-12-20 21:24:00
deflng a-z
Sub moz5()
Dim s(169)
T1# = Timer
s(1) = 2
s(2) = 3
s(3) = 5
s(4) = 7
k = 4
[color=FF00FF]iii = 3
iiii=25[color=000000]
For i = 11 To 1009 Step 2
For j = 2 To iii
[color=FF00FF] If i Mod s(j) Then else Exit For[color=000000]
Next
If j > iii Then
k = k + 1
s(k) = i
If i > iiii Then
iii = iii + 1
[color=FF00FF] iiii = s(iii)*s(iii)[color=000000]
End If
End If
Next
For i = 1011 To 1000000 Step 2
For j = 2 To iii
[color=FF00FF] If i Mod s(j) Then else Exit For[color=000000]
Next
If j > iii Then
k = k + 1
If i > iiii Then
iii = iii + 1
[color=FF00FF] iiii = s(iii)*s(iii)[color=000000]
End If
End If
Next
Debug.Print k, Timer - T1#
End Sub[/color]
7 楼
idealguy [专家分:110] 发布于 2011-12-21 22:37:00
[color=000000]不错,已经提高到6.5秒了(QB不编译)。
在VB下long的操作比Integer还快一点,但在16位的QB下,Integer显然快的多。
(改Integer后的程序见后面的代码, 时间缩短到4.2秒,编译2.9秒)
------------------------------------------------
BTW, 不编译 i mod s 较快, 全编译后, (i\s)*s)-i 较快(如果s是简单变量)
------------------------------------------------
此算法下程序已经很优化了。
如何再提高?
还是算法啊
-------------------------------------------------
[font=宋体]
DEFLNG A-K
DEFINT L-Z ' L-Z 为短整型
DIM S(169)
T1# = TIMER
S(1) = 2
S(2) = 3
S(3) = 5
S(4) = 7
k = 4
M1 = 3
IS2 = 25
FOR ni = 11 TO 1009 STEP 2
FOR n = 2 TO M1
IF ni = (ni \ S(n)) * S(n) THEN EXIT FOR
NEXT
IF n > M1 THEN
k = k + 1
S(k) = ni
IF ni > IS2 THEN
M1 = M1 + 1
IS2 = S(M1) * S(M1)
END IF
END IF
NEXT
FOR i = 1011 TO 1000000 STEP 2
FOR n = 2 TO M1
IF i MOD S(n) THEN ELSE EXIT FOR
NEXT
IF n > M1 THEN
k = k + 1
IF i > IS2 THEN
M1 = M1 + 1
IS2 = CLNG(S(M1)) * S(M1)
END IF
END IF
NEXT
PRINT k, TIMER - T1#
[/font][/color]
8 楼
idealguy [专家分:110] 发布于 2011-12-21 23:20:00
[color=000000]到1秒以内应该没问题。[/color]
潜水的人儿们,不要光潜水啊,会憋死的。
9 楼
幽灵密码 [专家分:3510] 发布于 2011-12-24 18:01:00
没办法= =。给水草缠上了,好不容易扯断了,憋死我了
10 楼
idealguy [专家分:110] 发布于 2011-12-25 11:18:00
[color=000000]应该启动筛法,先抛砖引玉。
本楼代码运行结果:(QB未编译)
Input a number within 2-1000000:? 1000000
TOTAL: 78498
Sieving Time(s): .6601563
Output Time(s): .5507813
代码:
[font=宋体]
DEFLNG A-Z
'
DATA 1,2,4,8,16,32,64,128,256,512
DATA 1024,2048,4096,8192,16384,-32768
'
DIM B(0 TO 15) AS INTEGER
FOR I = 0 TO 15
READ B(I)
NEXT
AAA:
INPUT "Input a number within 2-1000000:"; N
IF N < 2 THEN END
IF N > 1000000 THEN
PRINT "Out of range!": GOTO AAA
END IF
T! = TIMER
K = (N - 1) \ 32 + 1
'
REDIM A(K) AS INTEGER
FOR I = 0 TO K
A(I) = 0
NEXT
A(0) = 1
Q = INT(SQR(N))
Q = (Q - (Q MOD 2)) \ 2
H = (N - (N MOD 2)) \ 2
FOR I = 1 TO Q
R = I \ 16
T = A(R) AND B(I MOD 16)
IF T = 0 THEN
P = I + I + 1
M = I * (P + 1)
FOR J = M TO H STEP P
R = J \ 16
A(R) = A(R) OR B(J MOD 16)
NEXT J
END IF
NEXT I
Tm1! = TIMER
E = 1
'PRINT USING "##########"; 2;
FOR I = 1 TO H
R = I \ 16
T = A(R) AND B(I MOD 16)
IF T = 0 THEN
P = I + I + 1
IF P > N THEN GOTO BBB
E = E + 1
'PRINT USING "##########"; P;
END IF
NEXT I
BBB:
PRINT : PRINT "TOTAL:"; E
PRINT "Sieving Time(s):"; Tm1! - T!
PRINT "Output Time(s):"; TIMER - Tm1!
GOTO AAA
END
[/font]
[/color]
我来回复