傳統的解法就是利用"一個數 n 如果是合數,那麼它的所有的因子不超過sqrt(n)"這一性質來求解,時間復雜度為o(n*sqrt(n)),顯然當n很大時這種方法便不太適用。
(i=; i<MAX; ++ (j=; j<=()sqrt(i); ++ (i%j == (j > ( printf( }
prime[] = prime[] = count = (i=; i<MAXNUM; i+= (i% (j=; prime[j]<=()sqrt(i); ++ (i%prime[j] == (prime[j] > ( prime[count++] = (i=; i<count; ++ printf( }上面是本人根據題意的解法,下面是作者的解法。
gap = count = may_be_prime = prime[] = prime[] = prime[] = (prime[count] < may_be_prime += gap = - (i = ; prime[i]*prime[i] <= may_be_prime; i++ (may_be_prime % prime[i] == (prime[i] > ( prime[count++] = (i = ; i < count; i++ printf( }
(i=; i<MAXSIZE; ++ (i!= && i%== prime[i] = prime[i] = (i=; i<=()sqrt(MAXSIZE); i+= (j=i+i; j<MAXSIZE; j+= prime[j] = (i=; i<MAXSIZE; ++ printf( }上面應該是最常見的篩選法求質數的程序,在初始化數組時將2的倍數設為了NO,這樣做是為了簡化程序。 版本二:
(i=; i<MAXSIZE; ++ (i!= && i%== prime[i] = prime[i] = (i=; i<=()sqrt(MAXSIZE); i+= (j=; j<=MAXSIZE/i; ++ prime[i*j] = (i=; i<MAXSIZE; ++ printf( }版本二與版本一原理一樣,版本二的可讀性更好。 版本三(優化):
size = (MAXNUM - ) / + (i=; i<size; ++ prime[i] = (i=; i<size; ++ key = i + i + (j=key+*i*i+*i; j<size; j+= prime[j] = printf(, (i=; i<size; ++ printf(,*i+ }這裡的程序,prime[i]不再表示i為質數式合數,而表示2i+3為質數式合數,如果prime[i] = OK,則2i+3為質數,否則為合數。這樣做有什麼好處?因為所在的質都是奇數,2i+3能表示所有的質數(2除外),這樣做一方面減少了數組的空間,如需找出99以內的質數,用普通的篩選法則需定義一個100個長度的數組prime[100],而使用上面的程序只需定義一個(99-3)/2+1=49個長度的數組。空間個減少了一半。另一方面這做使得得到的質數全為奇數,直接排除了所有的偶數,提高了效率。程序中for(j=key+i;j<MAXSIZE/2-1;j+1=key){}這個for循環的作用是排除所有非質數,它是通過排除所有質數的奇數倍來排除奇數中的合數.具體操作如下,首先,確定一個質數2i+3,然後將2i+3的奇數倍對應的i值設為NO,如3(2i+3)為合數,則6i+9 = 2x+3,x=3i+3,於是將prme[3i+3]設為NO, 同理5(2i+3)=10+15=2x+3,x=5i+6,將prime[5i+6]設為NO。其中考慮到質數為5時會重復排除15(在3的時侯已經排除了),所以for循環中j=key+2*i*i+4*i,即從(2i+3)^2開始排除,而不是3(2i+3),為什麼3 5 7 9 11 ... ...中的素數n的倍數(奇數)要從n開始? 就是說從1開始和從n開始的效果是一樣,或者說n以前的奇數乘n都可以等於n以前(比n小的)素數的更大(比n大的)奇數倍數。由於n是奇數,可以設n以前(比n小的)的奇數為n-2i,比n大的奇數為n+2j;那麼我們的任務就是,證明n*(n-2i)可以等於m*(n+2j),其中m為小於n的素數,i、j都是正整數。即n(n-m)=2mj+2ni。這有變成證 明n-m是偶數,這是顯然的,兩個奇數之差必然是偶數。
版本四(優化):
size = (MAXNUM-)/+ (i=; i<size; ++ prime[i] = (i=;i<size;i+= (prime[(i-)/ (j=i*i;j<MAXNUM;j+=i<< prime[(j-)/] = printf(, (i=;i<size;++ printf(, (i<<)+ }版本五(線性篩選)
count = (i=; i<MAXNUM; ++ is_prime[i] = (i=; i<MAXNUM ; ++ (is_prime[i] == prime[count++] = (j=; j<count && (i*prime[j]) < MAXNUM; ++ is_prime[i*prime[j]] = (i % prime[j] == ) (i=; i<count; ++ printf( }