miller_rabin素数检测总结




miller_rabin素数检测 




今天学习了一下miller_rabin素数检测     稍微总结一下

首先用到两个定理





1、费马小定理

假如p是质数,且gcd(a,p)=1,那么a(p-1)≡1(mod p),即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。


2、二次探测定理

如果p是一个素数, 0





很可惜  费马小定理的逆命题是不成立的  即如果  a(p-1)≡1(mod p)推不出p是质数  但是也很庆幸  在大部分情况下它是成立的只有极少数的反例  所以我们依然可以用费马小定理的逆命题来概率性的判断素数  虽然会犯错  但是犯错概率也是相对较小的  为了进一步提高它判断质数的准确性  我们结合了定理二 






证明定理二

其实     x^2≡1(mod p) 

相当于    x^2-1≡0(mod p)   

也就是    (x+1)(x-1)≡0(mod p)

也就是说   p整除(x+1)或者(x-1)   所以   x=1 或者  x=p-1





然后就是素数检测的过程

对于待检测数p     在[2,p]中随机选取s次a     判断 a(p-1) ≡ 1(mod p)是否成立   一旦发现不成立则可判定p不是素数  为了提高正确的概率在求 a(p-1)%p 的过程中用到定理二    令p-1 =  2^t * k  (其中k是奇数)   然后  a(p-1)  就相当于  ak*2^t   也就是将 ak   平方t次  用x[i] 来表示平方i次的结果    如果发现 x[i] = 1    而x[i-1]既不等于1也不等于p-1    那么就可以判定p不是素数了     求 a(p-1)%p 的过程用的是快速幂    在用快速幂的过程中还用到了一个大数相乘取模的优化     即化乘法为加法    即模拟两个数相乘的二进制运算过程   每次相加取模    如果p成功通过检测则判定为素数否则为合数






快速幂算法不太清楚的可以看一下这里    http://blog.csdn.net/mm__1997/article/details/71794859








实现代码:

#include 
#include 
typedef long long LL;
LL x[105];
LL multi(LL a,LL b,LL p){//      化乘法为加法 
	LL temp=0;
	while (b){
		if (b&(LL)1) temp=(temp+a)%p;
		a=(a<<1)%p;b>>=1;
	}
	return temp;
}
LL qpow(LL a,LL b,LL p){//      快速幂 
    LL temp=1;
    while (b){
        if(b&(LL)1) 
			temp=multi(temp,a,p);
		b>>=1; a=multi(a,a,p);
    }
    return temp;
}
int miller_rabin(LL n){
	if (n==0||n==1) return 0;
	if (n==2) return 1;
	int s=10; LL k=n-1;
	int t=0;
	while (!(k&(LL)1)){t++;k>>=1;};//    k如果不是奇数将k转化为奇数 
	while (s--){
		LL a=rand()%(n-2)+2;//        随机取值 
		x[0]=qpow(a,k,n);
		for (int i=1;i<=t;i++){
			x[i]=multi(x[i-1],x[i-1],n);//     记录平方i次的结果 
			if (x[i]==1&&x[i-1]!=1&&x[i-1]!=n-1) return 0;
		}
		if (x[t]!=1) return 0;
	}
	return 1;
}
int main (){
	LL n;
	while (scanf ("%lld",&n)!=EOF){
		if (miller_rabin(n)) printf ("%lld is a prime\n",n);
		else printf ("%lld is not a prime\n",n);
	}
	return 0;
} 


Java实现代码:   http://blog.csdn.net/mm__1997/article/details/78307999

你可能感兴趣的:(算法,数论专题)