2020-04-12

轉(zhuǎn)自:判斷一個數(shù)是否為質(zhì)數(shù)/素數(shù)——從普通判斷算法到高效判斷算法思路_C/C++_huang_miao_xin的博客-CSDN博客

定義:約數(shù)只有1和本身的整數(shù)稱為質(zhì)數(shù)颁井,或稱素數(shù)。

計算機(jī)或者相關(guān)專業(yè),基本上大一新生開始學(xué)編程都會接觸的一個問題就是判斷質(zhì)數(shù)罪既,下面分享幾個判斷方法狠毯,從普通到高效于置。

1)直觀判斷法最直觀的方法劣光,根據(jù)定義,因?yàn)橘|(zhì)數(shù)除了1和本身之外沒有其他約數(shù)称开,所以判斷n是否為質(zhì)數(shù)亩钟,根據(jù)定義直接判斷從2到n-1是否存在n的約數(shù)即可。C++代碼如下:

bool isPrime_1( int num )

{? ? int tmp =num- 1; ??

?for(int i= 2;i <=tmp; i++) ? ? ?

? ? if(num %i== 0) ? ? ? ?

? ? ? ? return 0 ; ? ?

return 1 ;}

2)直觀判斷法改進(jìn)上述判斷方法鳖轰,明顯存在效率極低的問題清酥。對于每個數(shù)n,其實(shí)并不需要從2判斷到n-1蕴侣,我們知道焰轻,一個數(shù)若可以進(jìn)行因數(shù)分解,那么分解時得到的兩個數(shù)一定是一個小于等于sqrt(n)昆雀,一個大于等于sqrt(n)辱志,據(jù)此,上述代碼中并不需要遍歷到n-1狞膘,遍歷到sqrt(n)即可揩懒,因?yàn)槿魋qrt(n)左側(cè)找不到約數(shù),那么右側(cè)也一定找不到約數(shù)挽封。

C++代碼如下:

bool isPrime_2( int num )

{? ? int tmp =sqrt( num); ??

?for(int i= 2;i <=tmp; i++) ? ? ? ?

if(num %i== 0) ? ? ??

?? return 0 ; ??

?return 1 ;}

3)另一種方法方法(2)應(yīng)該是最常見的判斷算法了已球,時間復(fù)雜度O(sqrt(n)),速度上比方法(1)的O(n)快得多辅愿。最近在網(wǎng)上偶然看到另一種更高效的方法智亮,暫且稱為方法(3)吧,由于找不到原始的出處点待,這里就不貼出鏈接了鸽素,如果有原創(chuàng)者看到,煩請聯(lián)系我亦鳞,必定補(bǔ)上版權(quán)引用。下面講一下這種更快速的判斷方法;首先看一個關(guān)于質(zhì)數(shù)分布的規(guī)律:大于等于5的質(zhì)數(shù)一定和6的倍數(shù)相鄰燕差。例如5和7遭笋,11和13,17和19等等;證明:令x≥1徒探,將大于等于5的自然數(shù)表示如下:······ 6x-1瓦呼,6x,6x+1测暗,6x+2央串,6x+3,6x+4碗啄,6x+5质和,6(x+1),6(x+1)+1 ······可以看到稚字,不在6的倍數(shù)兩側(cè)饲宿,即6x兩側(cè)的數(shù)為6x+2,6x+3胆描,6x+4瘫想,由于2(3x+1),3(2x+1)昌讲,2(3x+2)国夜,所以它們一定不是素數(shù),再除去6x本身短绸,顯然车吹,素數(shù)要出現(xiàn)只可能出現(xiàn)在6x的相鄰兩側(cè)。這里有個題外話鸠按,關(guān)于孿生素數(shù)礼搁,有興趣的道友可以再另行了解一下,由于與我們主題無關(guān)目尖,暫且跳過馒吴。這里要注意的一點(diǎn)是,在6的倍數(shù)相鄰兩側(cè)并不是一定就是質(zhì)數(shù)瑟曲。此時判斷質(zhì)數(shù)可以6個為單元快進(jìn)饮戳,即將方法(2)循環(huán)中i++步長加大為6,加快判斷速度洞拨,原因是捏肢,假如要判定的數(shù)為n,則n必定是6x-1或6x+1的形式鸠信,對于循環(huán)中6i-1,6i掩浙,6i+1,6i+2,6i+3秸歧,6i+4厨姚,其中如果n能被6i,6i+2键菱,6i+4整除谬墙,則n至少得是一個偶數(shù),但是6x-1或6x+1的形式明顯是一個奇數(shù)经备,故不成立拭抬;另外,如果n能被6i+3整除侵蒙,則n至少能被3整除造虎,但是6x能被3整除,故6x-1或6x+1(即n)不可能被3整除蘑志,故不成立累奈。綜上,循環(huán)中只需要考慮6i-1和6i+1的情況急但,即循環(huán)的步長可以定為6澎媒,每次判斷循環(huán)變量k和k+2的情況即可,理論上講整體速度應(yīng)該會是方法(2)的3倍波桩。

代碼如下:bool isPrime_3( int num ){? ? ? ? ? ? ? ? //兩個較小數(shù)另外處理? ? ? ? ? ? ? ? if(num ==2|| num==3 )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 1 ;? ? ? ? ? ? ? ? //不在6的倍數(shù)兩側(cè)的一定不是質(zhì)數(shù)? ? ? ? ? ? ? ? if(num %6!= 1&&num %6!= 5)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 0 ;? ? ? ? ? ? ? ? int tmp =sqrt( num);? ? ? ? ? ? ? ? //在6的倍數(shù)兩側(cè)的也可能不是質(zhì)數(shù)? ? ? ? ? ? ? ? for(int i= 5;i <=tmp; i+=6 )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(num %i== 0||num %(i+ 2)==0 )? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return 0 ;? ? ? ? ? ? ? ? //排除所有戒努,剩余的是質(zhì)數(shù)? ? ? ? ? ? ? ? return 1 ;}算法性能測試:編寫測試代碼,使用較多數(shù)據(jù)測試比較幾種方法的判斷效率镐躲,數(shù)據(jù)量40w储玫,代碼如下:#include <iostream>#include <string>#include <ctime>#include <vector>using namespace std;bool isPrime_1( int num );bool isPrime_2( int num );bool isPrime_3( int num );int main(){? ? ? ? ? ? ? ? int test_num =400000;? ? ? ? ? ? ? ? int tstart ,tstop; //分別記錄起始和結(jié)束時間? ? ? ? ? ? ? ? //測試第一個判斷質(zhì)數(shù)函數(shù)? ? ? ? ? ? ? ? tstart=clock ();? ? ? ? ? ? ? ? for(int i= 1;i <=test_num; i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? isPrime_1(i );? ? ? ? ? ? ? ? tstop=clock ();? ? ? ? ? ? ? ? cout<<"方法(1)時間(ms):" <<tstop- tstart<<endl ;//ms為單位? ? ? ? ? ? ? ? //測試第二個判斷質(zhì)數(shù)函數(shù)? ? ? ? ? ? ? ? tstart=clock ();? ? ? ? ? ? ? ? for(int i= 1;i <=test_num; i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? isPrime_2(i );? ? ? ? ? ? ? ? tstop=clock ();? ? ? ? ? ? ? ? cout<<"方法(2)時間(ms):" <<tstop- tstart<<endl ;? ? ? ? ? ? ? ? //測試第三個判斷質(zhì)數(shù)函數(shù)? ? ? ? ? ? ? ? tstart=clock ();? ? ? ? ? ? ? ? for(int i= 1;i <=test_num; i++)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? isPrime_3(i );? ? ? ? ? ? ? ? tstop=clock ();? ? ? ? ? ? ? ? cout<<"方法(3)時間(ms):" <<tstop- tstart<<endl ;? ? ? ? ? ? ? ? cout<<endl ;? ? ? ? ? ? ? ? system("pause" );? ? ? ? ? ? ? ? return 0 ;}

————————————————

版權(quán)聲明:本文為CSDN博主「huang_miao_xin」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議萤皂,轉(zhuǎn)載請附上原文出處鏈接及本聲明撒穷。

原文鏈接:https://blog.csdn.net/huang_miao_xin/article/details/51331710

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裆熙,隨后出現(xiàn)的幾起案子端礼,更是在濱河造成了極大的恐慌,老刑警劉巖入录,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛤奥,死亡現(xiàn)場離奇詭異,居然都是意外死亡僚稿,警方通過查閱死者的電腦和手機(jī)凡桥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚀同,“玉大人缅刽,你說我怎么就攤上這事啊掏。” “怎么了衰猛?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵脖律,是天一觀的道長。 經(jīng)常有香客問我腕侄,道長,這世上最難降的妖魔是什么芦疏? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任冕杠,我火速辦了婚禮,結(jié)果婚禮上酸茴,老公的妹妹穿的比我還像新娘分预。我一直安慰自己,他們只是感情好薪捍,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布笼痹。 她就那樣靜靜地躺著,像睡著了一般酪穿。 火紅的嫁衣襯著肌膚如雪凳干。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天被济,我揣著相機(jī)與錄音救赐,去河邊找鬼。 笑死只磷,一個胖子當(dāng)著我的面吹牛经磅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钮追,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼预厌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了元媚?” 一聲冷哼從身側(cè)響起轧叽,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惠毁,沒想到半個月后犹芹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鞠绰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年腰埂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜈膨。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡屿笼,死狀恐怖牺荠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情驴一,我是刑警寧澤休雌,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站肝断,受9級特大地震影響杈曲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胸懈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一担扑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧趣钱,春花似錦涌献、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至井联,卻和暖如春卜壕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背低矮。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工印叁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人军掂。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓轮蜕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝗锥。 傳聞我的和親對象是個殘疾皇子跃洛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容