初等数论--同余--MILLER-RABIN素性检测算法优化
初等數論--同余--MILLER-RABIN素性檢測算法優化
- Euler theorem、Fermat's little theorem
- Primality Test: Fermat、MILLER-RABIN、IMPROVED
- 代碼驗證
博主是初學初等數論(整除+同余+原根),本意是想整理一些較難理解的定理、算法,加深記憶也方便日后查找;如果有錯,歡迎指正。
我整理成一個系列:初等數論,方便檢索。
這一章不同于前幾章,是我自己總結的素性檢測算法規律以及探索一些可優化的地方。
Euler theorem、Fermat’s little theorem
具體的定理內容以及證明,我在前幾章已經記錄過。
- 歐拉定理:設n∈N+,a∈Z,(a,n)=1,則aφ(n)≡1(modn)歐拉定理:設n\in N^+,a\in Z,(a,n)=1,則a^{\varphi(n)}\equiv 1(mod n)歐拉定理:設n∈N+,a∈Z,(a,n)=1,則aφ(n)≡1(modn)
- 費馬小定理:設n為素數,a∈Z,則an≡a(modn)費馬小定理:設n為素數,a\in Z,則a^n\equiv a(mod n)費馬小定理:設n為素數,a∈Z,則an≡a(modn)
可以看出,Fermat’s little theorem的條件更嚴格,要求是n為素數,而歐拉定理只要求a與n互素即可,并沒有要求n本身為素數。
目前我學習到的素性檢測算法都是以Fermat’s little theorem作為依據,應該是因為Fermat’s little theorem的條件,必須是素數。下面我具體來談談我學習到的幾個素性檢測算法。
Primality Test: Fermat、MILLER-RABIN、IMPROVED
素性檢測算法的目的都是一樣的:通過滿足某些條件,來判斷是素數的概率,檢測越多次概率越大,但是沒法把所有數都遍歷,所以概率不會到100%。
Fermat’s little theorem是通過n是素數的條件,推出a,n滿足哪些結論。素性檢測算法的手段也都是一樣的:通過a,n或者其他參數滿足哪些條件,判斷n是素數的概率。
- Fermat素性檢測算法:n為奇數,通過多次隨機取b∈Z,有(b,n)=1,判斷bn?1≡0(modn)b\in Z,有(b,n)=1,判斷b^{n-1}\equiv 0(mod n)b∈Z,有(b,n)=1,判斷bn?1≡0(modn)來逐步提高n是素數的概率。(n如果是奇合數,則被稱為對于基b的偽素數)
- MILLER-RABIN算法:更具化了n,使得n的條件更多,“n?1=2st,其中t為奇數,2?t,通過多次隨機取b∈Z,(b,n)=1,如果b和n滿足條件bt≡1(modn),或存在整數r,0≤r<s,使得b2rt≡?1(modn)"“n-1=2^st,其中t為奇數,2\nmid t,通過多次隨機取b\in Z,(b,n)=1,如果b和n滿足條件b^t\equiv 1(mod n),或存在整數r,0\le r< s,使得b^{2^rt}\equiv -1(mod n)"“n?1=2st,其中t為奇數,2?t,通過多次隨機取b∈Z,(b,n)=1,如果b和n滿足條件bt≡1(modn),或存在整數r,0≤r<s,使得b2rt≡?1(modn)"來逐步提高n是素數的概率。(n如果是奇合數,則被稱為對于基b的強偽素數)
- IMPROVED算法:更更具化了n,使得n的條件更多,“n?1=2k3lm,其中2?m且3?m,通過多次隨機取b∈Z,(b,n)=1,如果b和n滿足條件bm≡1(modn),或存在整數q,0≤q<l,使得b2?3qm+b3qm≡?1(modn)",或存在整數r,0≤r<k,使得b2r3lm≡?1(modn)"“n-1=2^k3^lm,其中2\nmid m且3\nmid m,通過多次隨機取b\in Z,(b,n)=1,如果b和n滿足條件b^m\equiv 1(mod n),或存在整數q,0\le q< l,使得b^{2·3^qm}+b^{3^qm}\equiv -1(mod n)",或存在整數r,0\le r< k,使得b^{2^r3^lm}\equiv -1(mod n)"“n?1=2k3lm,其中2?m且3?m,通過多次隨機取b∈Z,(b,n)=1,如果b和n滿足條件bm≡1(modn),或存在整數q,0≤q<l,使得b2?3qm+b3qm≡?1(modn)",或存在整數r,0≤r<k,使得b2r3lm≡?1(modn)"來逐步提高n是素數的概率。
可以看出,條件逐漸變得嚴格。有時候某些數可以通過Fermat素性檢測算法,卻不能通過MILLER-RABIN算法;可以通過MILLER-RABIN算法卻不能通過IMPROVED算法。
這是因為比對這兩種算法,其實是把Fermat素性檢測算法的一個條件進一步拆分成(s+1)個條件,MILLER-RABIN算法繼續到IMPROVED算法,也是把1個條件繼續拆分成(l+1)個條件。
我們是通過條件中有“0”項來判斷整體為“0”,從而素數可能性提高。也就是說,條件項皆不為0,則不能通過素性檢測。有沒有可能某一個數對于IMPROVED算法,皆不為0,可是對于MILLER-RABIN算法為0呢?應該是有的,即(l+1)個分項不為0,但是(l+1)個分項的乘積為0。即可能存在"b2?3qm+b3qm≡?1(modn)不滿足,bm≡1(modn)不滿足,卻滿足bt≡1(modn).b^{2·3^qm}+b^{3^qm}\equiv -1(mod n)不滿足,b^m\equiv 1(mod n)不滿足,卻滿足b^t\equiv 1(mod n).b2?3qm+b3qm≡?1(modn)不滿足,bm≡1(modn)不滿足,卻滿足bt≡1(modn)."
代碼驗證
具體數字需要代碼實現驗證,此工作正在進行中……
實現了Fermat素性檢測算法,和MILLER-RABIN素性檢測算法,以2為底,primeTable是0-10w內所有素數,生成算法沒有貼上來。
以下是Fermat素性檢測算法代碼:
from random import random# 利用輾轉相除法求最大公因數 def BFactor(a, b):# 若b>a,則交換兩個數的值if (b > a):t = aa = bb = tr = b # 初始化rwhile (r != 0):r = a % b # r為a/b的余數a = bb = rreturn a # 得到最后的a為(a,b)# n = int(input("請輸入需要檢測的整數n:")) # K = int(input("請輸入循環次數k:"))False_Prime_founded = []def fermat_test(n, K):k = 0while (k < K):flag = False# while (not flag):# b = int(random() * (n - 4) + 2) # 生成一個[2,n-2]之間的隨機整數# if (b >= 2 and b <= n - 2):# flag = Trueb = 2factor = BFactor(b, n) # 計算(b,n)r = (b ** (n - 1)) % n # 計算b^(n-1)modnprint("k=" + str(k + 1) + "時,取b=" + str(b), end=",")print("g=(" + str(b) + "," + str(n) + ")=" + str(factor), end=',')print("r=" + str(b) + "^" + str(n - 1) + "(mod " + str(n) + ")=" + str(r), end=',')if (factor > 1):print("故n=" + str(n) + "為合數")breakelif (r != 1):print("故n=" + str(n) + "為合數")breakelse:print("故n=" + str(n) + "可能為素數")k += 1if (k == K and n not in primeTable):False_Prime_founded.append(n)print("所以, n=" + str(n) + "可能為素數,n為素數的概率為" + str((1 - 1 / (2 ** k)) * 100) + "%")def run():for i in range(5, 100000):print(i)fermat_test(i, 1)print("找到的素數:" + str(False_Prime_founded))# 遍歷整數,直至找到偽素數run()以下是MILLER-RABIN素性檢測算法代碼:
import decimal from random import random from decimal import Decimal, localcontext import mathdecimal.getcontext().prec = 100000000# 輾轉相除法找最大公因數(a,b) def BFactor(a, b):if b > a:t = ab = ta = bq = bwhile (q != 0):q = a % ba = bb = qreturn b# n = int(input("請輸入需要檢測的整數n:")) # K = int(input("請輸入循環次數k:"))MI_False_Prime_founded = []def MILLER_RABIN(n, K):k = 0while (k < K):t = n - 1while (t % 2 == 0):print(t)t /= 2print("n: " + str(n) + "t: " + str(t))print("n-1/t:" + str((n - 1) / t))s = int(math.log((n - 1) / t, 2))print("s" + str(s))flag = False# while (not flag):# b = int(random() * (n - 4) + 2) # 生成一個[2,n-2]之間的隨機整數# if (b >= 2 and b <= n - 2):# flag = Trueb = 2factor = BFactor(b, n) # 計算(b,n)print("t: " + str(t))x = Decimal(Decimal(pow(Decimal(b), Decimal(t))) % Decimal(n)) # 計算b^tmodny = []print("vafac")for r in range(1, s):print("avsdfavafaa")print("s" + str(s))y.append(Decimal(pow(b, (Decimal(pow(2, r) * t)))))print(y)# print("包含2的次冪:"+str(y))# print("k=" + str(k + 1) + "時,取b=" + str(b), end=",")# print("g=(" + str(b) + "," + str(n) + ")=" + str(factor), end=',')# # print("r=" + str(b) + "^" + str(n - 1) + "(mod " + str(n) + ")=" + str(r), end=',')for i in y:print("i: " + str(i))print("n: " + str(n))print("i%n: " + str(int(i) % n))if int(i) % n == n - 1:print("故n=" + str(n) + "可能為素數")MI_False_Prime_founded.append(n)breakif factor > 1:print("factor: " + str(factor))print("數字1")print("故n=" + str(n) + "為合數")breakif x == 1 or x == -1:print("數字2")print("故n=" + str(n) + "可能為素數")MI_False_Prime_founded.append(n)# if p== -1 for p in y:# if p# print("故n=" + str(n) + "可能為素數")# k = k + 1else:print("故n=" + str(n) + "為合數")k += 1# if (k == K):# print("數字3")# MI_False_Prime_founded.append(n)# print("所以, n=" + str(n) + "可能為素數,n為素數的概率為" + str((1 - 1 / (2 ** k)) * 100) + "%")def run():for i in primeTable:print(i)MILLER_RABIN(i, 1)print("找到的素數:" + str(MI_False_Prime_founded))primeTable = [341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601,7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705,18705, 18721, 19951, 23001, 23377, 25761, 29341, 30121, 30889, 31417, 31609, 31621, 33153, 34945, 35333,39865, 41041, 41665, 42799, 46657, 49141, 49981, 52633, 55245, 57421, 60701, 60787, 62745, 63973, 65077,65281, 68101, 72885, 74665, 75361, 80581, 83333, 83665, 85489, 87249, 88357, 88561, 90751, 91001, 93961]run()找到的偽素數分別是:
-
Fermat算法找到的“素數”:[341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, 30121, 30889, 31417, 31609, 31621, 33153, 34945, 35333, 39865, 41041, 41665, 42799, 46657, 49141, 49981, 52633, 55245, 57421, 60701, 60787, 62745, 63973, 65077, 65281, 68101, 72885, 74665, 75361, 80581, 83333, 83665, 85489, 87249, 88357, 88561, 90751, 91001, 93961]
-
MILLER-RABIN算法找到的“素數”:[2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799, 49141, 52633, 65281, 74665, 80581, 85489, 88357, 90751]
總結
以上是生活随笔為你收集整理的初等数论--同余--MILLER-RABIN素性检测算法优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 初等数论--同余--MILLER-RAB
- 下一篇: 初等数论--同余方程--二元一次不定方程