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