簡體   English   中英

從2到n的素數列表(方案)

[英]List of prime numbers from 2 to n (scheme)

我正在嘗試創建一個過程,以建立從2到任意數字n的素數列表。 當然,這需要反復進行,但是我不完全知道自己在做什么錯。

(define (list-2-to-n n)
    (define (iter n result)
        (if (= n 0)
            result
        (if (< n 2)
           '()
            (if (= (remainder n 3) 0)
                (list-2-to-n (- n 1))
            (if (even? n)
                (list-2-to-n (- n 1))
                (iter (- n 1) (cons n result)))))))

    (iter n '())) 

每當測試用例通過過程時,它總是返回()

我做錯了。

讓我們來看看。 首先,您的縮進有誤導性。 它確實應該正確反映代碼的結構:

(define (list-2-to-n-0 n)       ; a global function
    (define (iter n result)     ; an internal function
        (if (= n 0)             
            result
            (if (< n 2)                        ; **else**
               '()
                (if (= (remainder n 3) 0)
                    (list-2-to-n (- n 1))
                    (if (even? n)              ; **else**
                        (list-2-to-n (- n 1))
                        (iter (- n 1) (cons n result)))))))
    (iter n '())) 

如果沒有,至少您應該在替代條款中清楚地標記一些注釋。

現在,您測試輸入數字是否可以被2或3整除,並以完全相同的方式響應。 確實應該將這兩種情況合而為一。 同樣,我們可以在這里使用cond ,而不是那么多的if嵌套:

(define (list-2-to-n-1 n)       ; a global function 
    (define (iter n result)     ; an internal function
        (cond
            ((= n 0)  result)
            ((< n 2)  '())
            ((or (= (remainder n 2) 0) (= (remainder n 3) 0))
              (list-2-to-n (- n 1))       ; calling a global function, and
            (else                         ;   returning its result
              (iter (- n 1)               ; calling internal function, and
                    (cons n result)))))   ;   returning its result
    (iter n '())) 

在此處調用全局函數意味着重新開始整個過程​​,它將使用()的初始累加器參數調用 iter器。 對於任何大於0的n初始值,您實際上想得到的n==0結果返回情況實際上是無法達到的,因為首先會遇到n < 2的情況,並且將返回( () (恰好是觀察到的行為)。

您不應該重新開始,即您應該始終調用內部函數。 您應該修復基本情況。 最后但並非最不重要的一點是,僅用5進行2或3的除數檢查是不夠的,因此讓我們在此處編寫isPrime ,然后在以后實現:

(define (list-2-to-n-1 n)       ; a global function
    (define (iter n result)     ; an internal function
        (cond
            ((< n 2)  result)
            ((not (isPrime n))
              (iter (- n 1) result))      ; calling internal function, without
            (else                         ;   altering the accumulator
              (iter (- n 1)               ; calling internal function, 
                    (cons n result)))))   ;   altering the accumulator
    (iter n '())) 

isPrime需要嘗試將n除以2,3,...不需要嘗試除以2以上的任何偶數,只要賠率就足夠了。 不需要嘗試任何可能的除數d ,使得d * d > n ,因為如果n = f * d, f <= df*d <= d*dn <= d*d

當然,嘗試除以9、15、77之類的任何組合也是多余的-如果其中任何一個除以n則它們的主要因子3、5、7、11之一也將其除,我們將更早地檢測到它們。 因此,實際上,僅嘗試除以質數就足夠了。 為此,您需要重組代碼,以便它以升序構建其素數列表,並使用其前綴部分不大於sqrt(k)來測試每個候選k

這稱為試驗分割算法。 然后有一個更快的Eratosthenes篩子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM