從費馬素數測試到Miller-Rabin素數測試

素數測試的基礎是費馬小定理:

對于素數p,任意0<a<p,有a^p \bmod p \equiv a ;變化形式為a^{p-1} \bmod p \equiv 1

費馬小定理逆定理不成立,所以費馬測試不保證正確。強化版測試方法就是Miller-Rabin素數測試:

在測試a^{p-1} \bmod p \equiv 1通過,且p-1還有因數2的情況下,進一步測試a^{(p-1)/2} \bmod p \equiv 1,如此重復除2的測試直到指數不再被2整除或者mod余數不再是1。最后那次測試如果mod結果不是1和p-1則可否定p是素數。

從費馬測試到Miller-Rabin測試的理論依據,網上很多博文都瞎抄了個二次探測定理,然而根本不適用,實際的推論過程如下。

初次測試指數n_{0}=p-1 ,其后每次測試都除2,依次記為n_{1},n_{2},n_{3}, ...

對于n_{i},如果可以繼續除2測試,即n_i/2=n_{i+1},那么可以做如下變換

a^{n_i} \bmod p \equiv 1

(a^{n_i}-1) \bmod p \equiv 0

(a^{n_{i+1}\times 2}-1) \bmod p \equiv 0

(a^{n_{i+1}}-1)(a^{n_{i+1}}+1) \bmod p \equiv 0

將mod改用整除形式表示

(a^{n_{i+1}}-1)(a^{n_{i+1}}+1) = p \times c

因為前提p是素數,無法再拆分因數,所以若左邊兩個括號不是直接等于p和c,就只能將c拆分因數

(a^{n_{i+1}}-1)(a^{n_{i+1}}+1) = p \times d\times e

即左邊兩個括號必有一個是p的整數倍,若是前者,則a^{n_{i+1}} \bmod p \equiv 1;若是后者,則a^{n_{i+1}} \bmod p \equiv p-1

特殊情況左邊有一個括號是0,那么a^{n_{i+1}} =1,同樣符合上述結論。

附一定范圍內Miller-Rabin素數測試的a值選擇,摘自wiki:

n<2047\Rightarrow a=2

n<1373653\Rightarrow a=2,3?(16bit符號數范圍內確保素數判斷正確)

n<4759123141\Rightarrow a=2,7,61(32bit符號數范圍內確保素數判斷正確)

n<18446744073709551616 \Rightarrow a=2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37(64bit符號數范圍內確保素數判斷正確)

c代碼實現:

int fast_power_mod(int base, int exp, int divisor) {
? ? int rmd = 1;
? ? while (exp != 0) {
? ? ? ? if (exp & 0x1)
? ? ? ? ? ? rmd = (rmd * base) % divisor;
? ? ? ? exp = exp >> 1;
? ? ? ? base = (base * base) % divisor;
? ? }
? ? return rmd;
}

type_prime miller_rabin(int num) {
? ? //special case for small number
? ? if?(num?<=?0)?return ILLEGAL;
????switch (num) {
? ? case 1:
? ? ? ? return ONE;
? ? case 2:
? ? case 3:
? ? ? ? return PRIME;
? ? default:
? ? ? ? break;
? ? }
? ? //for num < 4759123141, which means all int value
? ? const int TEST_BASE[] = {2, 7, 61}
? ? for (int i = 0; i < sizeof(TEST_BASE) / sizeof(TEST_BASE[0]); i++) {
????????int?base?=?TEST_BASE[i];
? ? ? ? if?(base?>=?num)?return?PRIME;
? ? ? ? int?exp?=?num?-?1;
? ? ? ? while?(true)?{
? ? ? ? ? ? int?rmd?=?fast_power_mod(base,?exp,?num);
? ? ? ? ? ? if?(rmd?==?num?-?1)?break;
????????????if?(rmd?!=?1)?return?COMPOSITE;
????????????//to?here?means?rmd==1
? ? ? ? ? ? if?((exp?&?0x1)?==?1)?break;
? ? ? ? ? ? exp?=?exp?>>?1;
? ? ? ? }
? ? }
? ? return PRIME;
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容