回 帖 发 新 帖 刷新版面

主题:[讨论]求1000000以内素数的个数的程序,比一比速度

[url=http://bbs.pfan.cn/post-379076.html]http://bbs.pfan.cn/post-379076.html[/url]


求1000000以内素数的个数的程序,比一比速度

回复列表 (共15个回复)

沙发

用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

板凳

QB 里面可以改为:
   dim s(1200)
......
        k = k + 1
        if k<1200 then s(k) = i

2楼代码经上述修改后QB测试通过,未编译运行时间约8秒。

3 楼

在QB里面,数组限制在64K以内,长整型为4,所以可以定义 s(16k)
但听你一解释,那就定义 1k 就足够了.

4 楼

[quote]在QB里面,数组限制在64K以内,长整型为4,所以可以定义 s(16k)
但听你一解释,那就定义 1k 就足够了.[/quote]
要比 1k 多一点才行。

5 楼

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 楼

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 楼

[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 楼

[color=000000]到1秒以内应该没问题。[/color]

潜水的人儿们,不要光潜水啊,会憋死的。

9 楼

没办法= =。给水草缠上了,好不容易扯断了,憋死我了

10 楼

[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]

我来回复

您尚未登录,请登录后再回复。点此登录或注册