素數檢測演算法

2021-08-04 12:52:34 字數 2226 閱讀 1891

因為1既不是素數也不是合數,所以下面的實現**中不考慮小於2的情況。

本文以c語言進行講解,建議對著完整的原始碼看。

最原始、最粗暴的方法就是從頭到尾逐個進行檢測,一旦遇到可被整除的數馬上返回false

bool is_prime_1(int n) 

}return

true;

}

該演算法時間複雜度為n2

n

2對於素數求解最簡單的優化,就是對n進行開方,減少迴圈次數。

bool is_prime_2(int n) 

}return

true;

}

該演算法時間複雜度為n−

−√n

使用乘法替代開方。數學庫中的sqrt開方無非是使用迭代法實現,cpu可能對這些數**算進行了優化,但與乘法相比sqrt顯得太過耗時。

bool is_prime_3(int n) 

}return

true;

}

很顯然除了2這個偶數是素數,其他所有的偶數都是合數,所以可以對輸入數進行奇偶檢測,優化演算法。

下面的奇偶檢測,使用二進位制位運算進行優化:計算機中的資料以2進製進行儲存,如果乙個整數是偶數,則最後一位肯定是0,(n & 1) == 0即可判斷乙個數是否為偶數。計算機位運算顯然比求餘運算速度快。

bool is_prime_4(int n) 

}return

true;

}

該演算法時間複雜度為n√

2 n

2從1開始數,每6個數為1組,其中每一組的2、3、4、6的數可以表示成6k+2、6k+3、6k+4、6k+6,很明顯這些數都能被2和3整出,所以我們對2和3進行檢測後,這些數就可以不用檢測了,而可能出現的素數在6k+1和6k+5位置上,這些數並沒有被檢測過,所以需要我們求取檢測(雖然這些檢測仍存在重複)。因為1既不是素數也不是合數,所以我們可以把需要檢測的數標記為6k-1和6k+1,並從5開始檢測。

演算法實現如下:

bool is_prime_5(int n) 

return

true;

}

該演算法的時間複雜度為n√

3 n

3聰明的你也許已經發現,前面說的偶數優化,也是用相同的原理。

我們可以根據這個規律更進一步,讓分組大小為2*3*5=30

我們只需要對7開始出現的素數進行檢測即可。

bool is_prime_6(int n) 

return

true;

}

void compare_and_test() ;

size_t length = sizeof(pfunc) / sizeof(pfunc);

size_t count = 0;

struct timespec start, end;

for (size_t i = 0; i < length; i++)

}timespec_get(&end, time_utc);

double duration = compute_duration(&end, &start);

printf("%d\n%lf\n", count, duration);}}

執行結果:

9592

1778329300.000000

9592

32828300.000000

9592

14184100.000000

9592

9072200.000000

9592

7018500.000000

9592

6040100.000000

Miller Rabin素數檢測演算法

對於給定的不小於3的奇數n,驗證次數t,miller rabin演算法如下 millerabin n,t 1.計算r,s,使滿足n 1 2的s次方 r 其中r是奇數 2.迴圈t次 1 隨機選取整數a,2 a n 2 2 計算y a的r次方 mod n 3 if y 1 y n 1 then j 1 ...

Miller Rabin素數檢測演算法

今天看了一下miller rabin素數檢測的演算法,總結了一下,希望這篇部落格對你們有幫助。先說幾個理論基礎 1.費馬小定理 假如p是質數,a是整數,且a p互質,那麼a的 p 1 次方除以p的餘數恆等於1,即 a p 1 1 mod p 但是反過來卻不一定成立,就是說,如果a p互質,且a p ...

Miller Rabin素數檢測演算法 acm模板

其基於以下兩個定理。fermat小定理 若n是素數,則 a a 0 mod n forall a a not equiv 0 pmod a a 0 m odn 有an 1 1 modn a equiv 1 pmod an 1 1 mod n 二次探測定理 若n是素數,則x2 1 mo dn x 2 ...