問題2.3求質數(prime1.c )
試編寫乙個程式,找出前n (如200)個質數。如果沒有進一步要求,這不是難題。 但在此希望從所知的、使用除法的方法中,用最快的辦法來編寫程式。
【說明】
可能最先想到的辦法,就是讓某個變數i從2變到n,然後檢查它是不是質數,如果是就顯示出來,如果不是,就檢查下乙個。這是正確的做法,但卻沒有注意到乙個小細節, 因而使程式執行速度變慢。當然,2是質數,但所有2的倍數都不是質數,如果令i從2 變到n,不就很冤枉地測試了 4,6,8,10,…這些數?所以第一點提示是測試2,3,5,7,…,n,即 2與所有奇數就足夠了。同理,3是質數,但6,9,12,…這些3的倍數卻不是,因此,如果能夠把2與3的倍數都跳過去而不測試,任意連續的6個數中,就只會測試兩個而已。以6n,6n+1,6n+2,6n+3,6n+4,6n+5 為例,6n,6n+2,6n+4 是偶數,又 6n+3 是 3 的倍數,所以如果 把2與3的倍數都不理會,要測試的數就只留下6n+1與6n+5而已,因而工作量只是前述想法的2/6=1/3,應該用這個方法去編寫程式。
假設i是如上述的乙個數(不是2與3的倍數),如何測試i是個質數呢?按照定義,i 如果是質數,也就只有1與i可以除盡自己,所以可以用2,3,4,5,6,…,i-1去除i,如果都除 不盡(餘數不是0), i就是質數。觀點也對,但卻與上一點一樣地笨拙。當i>2時,有哪 1個數i可以被i-1除盡的?沒有,為什麼?如果i不是質數,那麼i=a*b,此地a與b既 不是i又不是1;正因為a>1,a至少是2,因此b最多是i/2而已,去除i的數用不著是 2,3,4,…i-1;而用2,3,4,…,i/2就可以了。不但如此,因為i=a*b,a與b不能大於i^½,為什麼呢?如果i不是質數,它的因子最大就是換言之,用2,3,4,5,…,i^½去除i就行了。
但是,用2,3,4,5,…,i^½去除 i 也是個浪費。就像是前一段所說的,2除不盡,2的倍數 也除不盡;同理,3除不盡,3的倍數也除不盡……最理想的方法就是用質數去除i,因為 在前一段的提示,i不是2與3的倍數,所以就用5,7,11,13,17,19,…這些比 i^½ 小的質數去 除i即可。但問題是這些質數從何而來?這比較簡單,可以準備乙個陣列prime,用來存放找出來的質數,一開始它應該有2、3與5。於是當i=5,7,11,13,17,19,23,25,29,…這些不是2與3 的倍數時,就用prime中小於 i^½ 的數去除 i 即可,如果都除不盡,i就是質數,把它放入 prime中,因此prime中的質數雜會越來越多,直到滿足所要的個數為止。
不妨用這段說明來編寫程式,不過應注意下面幾點:
(1)不要處理2與3的倍數(見第一段)。
(2)用質數去除(見第
二、三段)。
(3)用i^½可能會有問題,為什麼?有什麼方法可以解決?
【解答】
程式的結構本身並不複雜,只解釋幾個重點而已。
第一,看如何跳過2與3的倍數。在問題說明中,看過在6n,6n + 1,6n+2,611+3,6n+4 與6n+5中,只有6n+1與6n+5要做測試,看看是否是質數,看看這兩個數的相對位置。上一組最後乙個要測試的值,與這一組第乙個要測試的值的距離是2; 而同一組中要測試的兩個值之間的距離是4。所以從5起,依次加2、加4、加2、加4、… 就可以得到5,7,11,13,17,19,…這些要測試的值了。但是2+4=6,可以用乙個變數(程式中是 gap),令它的值在開始時為2,下乙個值就是6-gap (就是4),再下次6-gap不就是2了 嗎?這就是程式中gap=6-gap的意義。
第二,不能比較是否小於i^½,原因是對某些i而言,i^½可能並不精確。舉個例子,如 果i=121,在數學上i^½自然是11,但是計算機算出來的結果很可能是10.999999,於是去 除i的數就是2,3,5,7而不含11,因此變成121是個質數了。解決之道很簡單,不要用開方, 用平方即可。例如,如果p*q【程式說明】
在程式中,prime是用來存放找出來的質數的,一開始時就有了 2,3,5這3個最基本 的質數(都小於6)。gap的初值是2,它的值依次是2,4,2,4,…,在解答中見過了。count 計算到目前為止一共找到了多少個質數,2,3,5已經放入prime,所以count的值是3。於 是當count比maxsize小的時候,就產生下乙個要檢查的數,存入may一be一prime,進入 for迴圈做檢查工作;如果是個質數,那麼for迴圈中的if就永遠是假,is一prime的值就不曾被改變,因此就把它存入prime中,這就是程式的基本結構。
#include #define maxsize 100
#define yes 1
#define no 0
int main()
if(is_prime)
prime[count++]=may_be_prime; }
printf("\nprime number generation program");
printf("\n******************************=\n");
printf("\nfirst %d prime numbers are :\n", count);
for (i = 0; i < count; i++)
return 0;
}
《C語言名題精選百則 7》
這次終於遇到點挑戰了,先上題目吧 我的答案 trente.c includevoid test int testnum,int limit void print int v,i,n,g,t,c,q,r,e int main void test int testnum,int limit int ea...
C語言精選名題百則 第一章(序曲)
問題1.1最長平台 plateau.c 已知乙個已經從小到大排序的陣列,這個陣列中的乙個平台 plateau 就是連續的一串 值相同的元素,並且這一串元素不能再延伸。例如,在1,2,2,3,3,3,4,5,5,6中1,2.2,3.3.3,4,5.5,6 都是平台。試編寫乙個程式,接收乙個陣列,把這個...
C程式語言 第二章 筆記
第二章 型別 運算子與表示式 變數 變數和常量是程式處理的兩種基本資料物件 由於庫例程的名字通常以下劃線開頭,因此變數名不要以下劃線開頭 大小字母有區別 變數名使用小寫字母,符號常量名全部使用大寫字母 所有關鍵字都必須小寫 所有變數都必須先宣告後使用 任何變數的宣告都可以使用const限定符限定。該...