ミラー-ラビン素数判定法
定理 1
奇数 を のように表しよう。 そして全ての に対して、 が存在して上記を満たすなら、 は合成数である。
説明
計算量が増えるだけ、フェルマーの小定理を通過する合成数も排除する可能性がある。
例えばカーマイケル数である は、 が であるので、 が素数でないことを早く確認できる。この時、判断に使用された のような数をミラー・ラビン証人miller-Rabin Witnessという。もちろん、全ての がテストを通過しても が素数だとは限らない。
証明
でなければ、 の可能性がある。
でもなければ、 の可能性がある。
同様に、 の少なくとも一つが で と合同であるか、初めから よって、 が素数なら、 か少なくとも一つの に対して 最後に、対偶法により証明が終わる。
■
コード
以下は、Rで実装されたミラー・ラビンテストで、計算のために連続二乗法とユークリッドの互除法が使用されている。
FPM<-function(base,power,mod) #It is equal to (base^power)%%mod
{
i<-0
if (power<0) {
while((base*i)%%mod != 1) {i=i+1}
base<-i
power<-(-power)}
if (power==0) {return(1)}
if (power==1) {return(base%%mod)}
n<-0
while(power>=2^n) {n=n+1}
A<-rep(1,n)
A[1]=base
for(i in 1:(n-1)) {A[i+1]=(A[i]^2)%%mod}
for(i in n:1) {
if(power>=2^(i-1)) {power=power-2^(i-1)}
else {A[i]=1} }
for(i in 2:n) {A[1]=(A[1]*A[i])%%mod}
return(A[1])
}
gcd <- function(a, b) {
if (b>a) {i=b; b=a; a=i;}
while(b) {
temp = b
b = a %% b
a = temp
}
return(a)
}
MR.test<-function(n)
{
q=n-1
k=0
while(!q%%2) {q=q/2; k=k+1+6}
for(i in 2:(n-1))
{
if (gcd(i,n)!=1) {return(paste(i,"is a Miller-Rabin witness!"))}
A=FPM(i,q,n)
a=A
for(j in 0:(k-1))
{
if( a==(n-1) )
{
j=0
break
}
a=(a^2)%%n
}
if (j==(n-1) & A != 1) {return(paste(i,"is a Miller-Rabin witness!"))}
}
paste(n,"passes the Miller-Rabin test!")
}
MR.test(17)
MR.test(121)
MR.test(341) #Almost composite yields fermat witness 2, but 341=11*31 doesn't.
MR.test(561) #Carmicheal number 56 = 3*11*17
MR.test(1031) #1031 is a prime
MR.test(1105) #Carmicheal number 1105 = 5*13*17
MR.test(1729) #Carmicheal number 1729 = 7*13*19
MR.test(41041) #Carmicheal number 41041 = 7*11*13*41
以下はコードを実行した結果だ。
フェルマーテストと異なり、ミラー・ラビンテストは 、、、 といったカーマイケル数も捕まえることができる。
Silverman. (2012). A Friendly Introduction to Number Theory (4th Edition): p137. ↩︎