Algorithm Gossip (15) 篩選求質數(Eratosthenes )

前言

This Series aritcles are all based on the book 《經典算法大全》; 對於該書的所有案例進行一個探究和拓展,並且用python和C++進行實現; 目的是熟悉常用算法過程中的技巧和邏輯拓展。

提出問題

15.Algorithm Gossip: 篩選求質數(Eratosthenes )

說明

除了自身之外,無法被其它整數整除的數稱之爲質數.

篩選原理

逐步選出小質數對應的集合元素, 直到篩選質數到 sqrt(N)。

分析和解釋

計算素數的一個方法是埃氏篩法,它的算法理解起來非常簡單:

首先,列出從2開始的所有自然數,構造一個序列:

2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …

取序列的第一個數2,它一定是素數,然後用2把序列的2的倍數篩掉:

3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …

取新序列的第一個數3,它一定是素數,然後用3把序列的3的倍數篩掉:

5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …

取新序列的第一個數5,然後用5把序列的5的倍數篩掉:

7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, …

不斷篩下去,就可以得到所有的素數。

用Python來實現這個算法,可以先構造一個從3開始的奇數序列:

代碼

C語言有待改進的示例

#include <stdio.h>
#include <stdlib.h>
#define N 1000
int main(void) {
    int i, j;
    int prime[N+1];
    for(i = 2; i <= N;i++)
        prime[i] = 1;
    for(i = 2; i*i <= N;i++) {
        if(prime[i] == 1) {
            for(j = 2*i; j <= N;j++) {
                if(j % i == 0)
                    prime[j] = 0;
                }
            }
        }
    for(i = 2; i < N;i++) {
        if(prime[i] == 1) {
            printf("%4d ", i);
            if(i % 16 == 0)
                printf("\n");
            }
        }
    printf("\n");
    return 0;
    }

python 的 fitter 實現

def _odd_iter():
    n = 1
    while True:
        n = n + 2
        yield n

# 篩選函數
def _not_divisible(n):
    return lambda x: x % n > 0

#生成器, 不斷返回素數
def primes():
    yield 2
    it = _odd_iter() # 初始序列
    while True:
        n = next(it) # 返回序列的第一個數
        yield n
        it = filter(_not_divisible(n), it) # 構造新序列

##主函數
for n in primes():
    if n < 1000:
        print(n)
    else:
        break

PS, 對 fitter , yied 不熟悉的可以百度瞭解下生成器和迭代器。

yied 主要用於不斷生成目標返回到元組的一種append方式 -> 生成器, fitter 爲刪選機制。

拓展和關聯

後記

參考書籍

  • 《經典算法大全》
  • 維基百科
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章