因为文中存在公式,只能用图片方式上传了!
以下为C语言源代码:
#include <stdio.h>
typedef long long unsigned LLU;
typedef int BOOL;
#define TRUE 1
#define FALSE 0
BOOL isPrime(LLU n) { //这是传统的方法,用于与Miller-Rabin算法的结果进行对比。
if( (n&1)==0 || n%5==0)
return FALSE;
LLU i,bnd;
bnd=sqrt(n);
for(i=2; i<=bnd; i++)
if(n%i==0)
return FALSE;
return TRUE;
}
//实现(a*b)%c,用类似快速幂的方式实现。
//将模运算下的乘法用加法实现的思想是时间换空间。
//这可以作为典型的时间换空间的例子。
LLU quickMult(LLU a,LLU b,LLU c){
LLU result=0;
while(b>0) {
if(b&1)
result=(result+a)%c;
a=(a+a)%c;
b>>=1;
}
return result;
}
//请注意,计算快速幂时,因为变量的数据类型为long long,是64bits长度的整数。
//a的值不能大于(2的32次方-1)≈4000000000
//否则,计算a*a时会越界,超过64bits整数的表示范围。
//例如a,b,c分别为:7087881096594 10000000000036 10000000000037时,
//正确结果 (a^b)%c=1,但是,在此计算的结果不为1。
//因此,可以改进为用“快速乘”代替*乘法运算符,能更加充分第利用64的long long unsigned型的存储空间。
//这个例子可以作为算法改进从O(n)到O(lg(n))的进步的例子。
LLU quickPower(LLU a,LLU b,LLU c) {
LLU result=1;
while(b>0) {
if(b&1)
//result=result*a%c; //此为直接乘法
result=quickMult(result,a,c);
//a=a*a%c; //此为直接乘法
a=quickMult(a,a,c);
b>>=1;
}
return result;
}
//如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
BOOL MillerRabinPrimeTest(LLU n) {
LLU d,x,newX,a=1;
int i;
for (i=0; i<4; i++)
a*=rand();
a=a%(n-3)+2;//随机第选取一个a∈[2,n-2]
//printf("随机选取的a=%lld\n",a);
int s=0;//s为d中的因子2的幂次数。
d=n-1; //d取初值n-1
while( (d&1)==0) {//将d中因子2全部提取出来。
s++;
d>>=1;
}
x=quickPower(a,d,n);
for(i=0; i<s; i++) { //进行s次二次探测
newX=quickPower(x,2,n);
if(newX==1 && x!=1 && x!=n-1)
return FALSE; //用二次定理的逆否命题,此时n确定为合数。
x=newX;
}
if(x!=1)
return FALSE; //用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。
return TRUE; //用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。
}
//经过连续特定次数的Miller-Rabin测试后,
//如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
BOOL isPrimeByMR(LLU n) {
if((n&1)==0 || n%5==0)
return FALSE;
int i;
for (i=0; i<100; i++)
if(MillerRabinPrimeTest(n)==FALSE)
return FALSE;
return TRUE;
}
//对比传统方法和Miller-Rabin算法的结果
void check(LLU n) {
char isRight;
BOOL resultA,resultB;
resultA=isPrime(n);
resultB=isPrimeByMR(n);
if(resultA==resultB) {
isRight='V';
printf("%c,%llu %d %d\n",isRight,n,resultA,resultB);
} else {
isRight='X';
printf("%c,%llu %d %d\n",isRight,n,resultA,resultB);
}
}
//测试任务:在本人笔记本电脑上测试,N=10的18次方至N+10之间的质数为:
//1000000000000000003
//1000000000000000009
//Miller-Rabin算法的速度:0.22秒
//常规算法:22秒
int main() {
srand(time(NULL));
LLU i,n,N;
N=1000000000000000000;
BOOL result;
for(i=N; i<N+10; i++) {
n=i;
//check(n);
//result=isPrime(n);
result=isPrimeByMR(n);
if(result==TRUE)
printf("%llu\n",n);
}
return 0;
}
以下为Python语言源代码:
import math
import randomdef isPrime(n): #这是传统的方法,用于与Miller-Rabin算法的结果进行对比。if (n & 1) == 0 or n % 5 == 0:return Falsebnd = int(math.sqrt(n))for i in range(2, bnd + 1):if n % i == 0:return Falsereturn True# 实现(a*b)%c,用类似快速幂的方式实现。
# 将模运算下的乘法用加法实现的思想是时间换空间。
# 这可以作为典型的时间换空间的例子。
def quickMult(a, b, c):result = 0while b > 0:if b & 1:result = (result + a) % ca = (a + a) % cb >>= 1return result#因为Python支持大整数运算,所以在此也可以不用快速乘法,而直接使用乘法*。
def quickPower(a, b, c):result = 1while b > 0:if (b & 1):# result=result*a%c #此为直接乘法result = quickMult(result, a, c)# a=a*a%c #此为直接乘法a = quickMult(a, a, c)b >>= 1return result#如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def MillerRabinPrimeTest(n):a = random.randint(2,n-2) #随机第选取一个a∈[2,n-2]# print("随机选取的a=%lld\n"%a)s = 0 #s为d中的因子2的幂次数。d = n - 1while (d & 1) == 0: #将d中因子2全部提取出来。s += 1d >>= 1x = quickPower(a, d, n)for i in range(s): #进行s次二次探测newX = quickPower(x, 2, n)if newX == 1 and x != 1 and x != n - 1:return False #用二次定理的逆否命题,此时n确定为合数。x = newXif x != 1: # 用费马小定理的逆否命题判断,此时x=a^(n-1) (mod n),那么n确定为合数。return Falsereturn True # 用费马小定理的逆命题判断。能经受住考验至此的数,大概率为素数。# 经过连续特定次数的Miller-Rabin测试后,
# 如果返回值为TRUE表示n为素数,返回值为FALSE表示n为合数。
def isPrimeByMR(n):if ((n & 1) == 0 or n % 5 == 0):return Falsefor i in range(100):if MillerRabinPrimeTest(n) == False:return Falsereturn True#对比传统方法和Miller-Rabin算法的结果
def check(n):resultA = isPrime(n)resultB = isPrimeByMR(n)if resultA == resultB:isRight = 'V'print("%c,%u %d %d" % (isRight, n, resultA, resultB))else:isRight = 'X'print("%c,%u %d %d" % (isRight, n, resultA, resultB))# 测试任务:在本人笔记本电脑上测试,N=10的18次方至N+10之间的质数为:
# 1000000000000000003
# 1000000000000000009
# Miller-Rabin算法的速度:0.22秒
# 常规算法:22秒
# python的常规算法,耗时更长。
def main():# freopen("result.txt","w",stdout)random.seed()# res=quickPower(2,10,7)# print("%u"%res)N = 1000000000000000000for i in range(N, N + 10):n = i#check(n)# n=int(input())#result=isPrime(n)result = isPrimeByMR(n)if result == True :print("%u" % n)return 0# print(isPrime(1000000000000000003))
# a, b, c = [int(e) for e in input().split(" ")]
# print(quickPower(a,b,c))
# # 7087881096594 10000000000036 10000000000037 =1
main()