Python 3.x 素性测试:如何确保不测试已经测试过的数字的倍数?
这是我的密码:Python 3.x 素性测试:如何确保不测试已经测试过的数字的倍数?,python-3.x,math,Python 3.x,Math,这是我的密码: from math import sqrt def isPrime(value): a = [] for i in range(1, int(sqrt(value)) + 1): if value <= 3: return value if value % 2 == 0: break if value % i == 0: a.appen
from math import sqrt
def isPrime(value):
a = []
for i in range(1, int(sqrt(value)) + 1):
if value <= 3:
return value
if value % 2 == 0:
break
if value % i == 0:
a.append(i)
i += 1
continue
elif value % i != 0:
a = a
continue
if len(a) == 1:
return value
else:
pass
从数学导入sqrt
def iPrime(值):
a=[]
对于范围(1,int(sqrt(值))+1)内的i:
用Rabin-Miller算法进行if值素性检验
使用
导入数学
def初始_数据(编号):
计数=0
goree=数字-1
楼层=数量//2
当goree%2==0时:
goree/=2
计数+=1
结果=[发言,计数]
返回结果
def测试_值(num):
测试值=[]
如果num<2047:
测试值=[2]
elif num<1373653:
测试值=[2,3]
elif num<9080191:
测试值=[31,73]
elif num<25326001:
测试值=[2,3,5]
elif num<3215031751:
测试值=[2,3,5,7]
elif num<4759123141:
测试值=[2,7,61]
elif num<1122004669633:
测试值=[2,13,23,1662803]
elif num<2152302898747:
测试值=[2,3,5,7,11]
elif num<34749660383:
测试值=[2,3,5,7,11,13]
elif num<341550071728321:
测试值=[2,3,5,7,11,13,17]
elif num<382512356546413051:
测试值=[2,3,5,7,11,13,17,19,23]
elif num<2**64:
测试值=[2,3,5,7,11,13,17,19,23,29,31,37]
elif num<31866585834031151167461:
测试值=[2,3,5,7,11,13,17,19,23,29,31,37]
elif num<3317044064679887385961981:
测试值=[2,3,5,7,11,13,17,19,23,29,31,37,41]
返回测试值
def rabin_miller(数字):
基本素数=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197,
199, 211, 223, 227, 229, 233, 239,241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313,
317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449,
457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521,523, 541, 547, 557, 563, 569, 571, 577, 587,
593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661,673, 677, 683, 691, 701, 709,
719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991,
997]
如果num以下是随机试验的实施:
import random
#The following function finds s and d in
#n-1 = 2^s*d with d odd
def findSD(n):
s = 0
d = n-1
while d % 2 == 0:
s = s + 1
d = d//2
return s,d
def checkBase(a,n):
s,d = findSD(n)
x = pow(a,d,n)
if x == 1 or x == n-1:
return "probable prime"
else:
for i in range(s-1):
x = pow(x,2,n)
if x == 1:
return "composite"
elif x == n-1:
return "probable prime"
#if you get to this stage, -1 not reached despite s-1
#squarings -- so must be composite
return "composite"
def MSR(n,k):
#tests is an odd number is prime
for i in range(k):
a = random.randint(2,n-2)
if checkBase(a,n) == "composite":
return "composite"
#if you get here n has survived k potential witnesses, so
return "probable prime"
def prime(n):
smallPrimes = [2,3,5,7,11,13,17,19]
for p in smallPrimes:
if n == p:
return True
elif n % p == 0:
return False
if MSR(n,20) == "composite":
return False
else:
return True
def prime(n):
smallPrimes = [2,3,5,7,11,13,17,19]
for p in smallPrimes:
if n == p:
return True
elif n % p == 0:
return False
if MSR(n,20) == "composite":
return False
else:
return True
您可以使用它来搜索素数:
def findPrime(maxN):
while True:
n = random.randint(3,maxN)
if prime(n):
return n
典型运行:
>>> findPrime(2**512)
3416363469318261052788311737860856549293100664891633139661459849835325883152102949928216754211470387640525391249585700324869443369023574938398397274187333
如果你真的想测试大数,那么就放弃用试算法测试素数的想法,转而学习米勒-拉宾测试。无论如何,这是一个被广泛研究的问题。你有没有尝试过研究文献?@JohnColeman我不了解Miller-Rabin测试的实现,你能帮忙吗?这是一个有点复杂的话题。如果维基百科的文章还不够,我推荐林恩·玛格丽特·巴顿(Lynn Margaret Batten)的《公钥密码术》(Public Key Cryptography)一书作为一个很好的介绍,如果你想了解一些理论的话。它有一章介绍素性测试(以及很容易翻译成Python的Maple代码)。由于Python的pow
函数已经实现了一个高效的模幂运算,因此可以用几十行Python代码编写一个高效的Miller-Rabin测试。@JohnColeman感谢您的建议,这就是我可以利用我找到的资源所做的。让我知道是否有任何改进可以做。看起来不是很好-Rabin@JohnColeman它确实更具确定性,但基础是米勒·拉比尼,看,你使用的是一个确定性变量,它的正确性取决于黎曼假设是否成立。为什么要避免概率版本,因为在运行确定性版本时,获得误报的概率可能会低于随机硬件故障的概率(在实际硬件上运行的任何计算机程序都不能提供绝对确定性)。无论如何,我以前读过这个确定性变体,但没有看到它在Python中实现,所以+1。依赖未经证实的假设的理论缺陷不太可能有任何实际影响。尽管无法量化,但让这个算法证明一个复合数为素数,从而推翻黎曼假设的可能性是微乎其微的。我曾经见过一个类似的代码,但你能告诉我它的运行时间吗?我写的这篇文章花了很长时间来评估前100万个素数的总和(实际上超过30分钟),因为前100万个素数的总和使用埃拉托斯烯的筛子来生成列表,而不是测试每个候选者。众所周知,第n个素数是<n*(log(n)+log(log(n))
(参见维基百科页面上的素数定理)计算出来大约有1645万个-所以筛选这个范围。如果你找到了所有的素数-无需逐个测试。多亏了这个技巧,埃拉托什尼的筛子很容易实现,而且运行速度非常快,特别是为了对连续的素数求和。对于前100万个素数,我有6秒的运行时间。
>>> findPrime(2**512)
3416363469318261052788311737860856549293100664891633139661459849835325883152102949928216754211470387640525391249585700324869443369023574938398397274187333