找到一个数字“内”的最大素数

时间:2014-01-16 02:41:20

标签: python performance optimization

对于这个问题,我需要在更大的数字中找到最大的素数。出于示例的目的,假设较大的数字是“123456789”,那么我需要检查的一些数字是12,456,234567等。

我写了一些Python代码来解决这个问题,但是对于我想要检查的数字,它的运行速度非常慢。我正在使用的实际数字大约是10000位数,所以我需要查看很多数字。这是我的代码:

num = "123456789"

def isPrime(n):
# 0 and 1 are not primes
if n < 2:
    return False
# 2 is the only even prime number
if n == 2:
    return True
# all other even numbers are not primes
if not n & 1:
    return False
# range starts with 3 and only needs to go up the squareroot of n
# for all odd numbers
for x in range(3, long(n**0.5)+1, 2):
    if n % x == 0:
        return False
return True

def largestPrime():
    largest = 2
    for i in range(0,len(num)):
        for j in range(i+1,len(num)):
            if isPrime(long(num[i:j])):
                if long(num[i:j]) > largest:
                    largest =long(num[i:j])
    print largest

def main():
    largestPrime()

main()

我很确定这段代码会给出正确的答案,但正如我所说,它真的很慢。任何人都可以帮我弄清楚如何加快速度吗?

感谢您的帮助!

3 个答案:

答案 0 :(得分:3)

我可能会使用以总位数开头并查看是否为素数的策略。然后继续向左移动数字,同时向左移动以查看是否为素数。让我用一个例子来解释:

123456789

First check the 9-digit number: 123456789
Then check the 8-digit numbers: 23456789, 12345678
Then Check the 7-digit numbers: 3456789, 2345678, 1234567
etc.

答案 1 :(得分:1)

我看到的一个问题是,对于某些大数字,您将多次测试相同的数字。例如,对于'123456712345671234567',您的代码将测试'1234567'3次。我建议你制作一个不包含重复的集合,然后对每个数字进行主要测试。我也认为排序数字是一个好主意,因为我们可以在找到第一个素数后停止。

接下来,如果您正在处理大数字(例如10000位数),我建议使用统计素性测试。下面我使用来自wikipedia的伪代码进行了Miller-Rabin素性测试。

我几乎重写了你的代码:P

import random
num = '3456647867843652345683947582397589235623896514759283590867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876867843652345683947582397589235623896514759283590784235876784235876324650'

def probablyPrime(num, k):
    """Using Miller-Rabin primality test"""
    if num == 2 or num == 3:
        return True
    if num < 2:
        return False
    if not num & 1:
        return False

    # find s and d such that n−1 = (2**s)*d with d odd
    d = (num-1) >> 1
    s = 1
    while not (d & 1):
        d = d >> 1
        s += 1

    # run k times
    for _ in range(k):
        a = random.randint(2, num-2)
        x = pow(a, d, num)  # more efficient than  x = a**d % num
        if not (x == 1 or x == num-1):
            for _ in range(s-1):
                x = (x**2) % num
                if x == 1:
                    return False
                if x == num-1:
                    break
            if not x == num-1:
                return False
    return True


def largestPrime(num):
    num_list = set([])
    for i in range(0,len(num)+1):
        for j in range(i+1,len(num)+1): 
            inum = int(num[i:j])
            # Don't append numbers that have already appeared
            if inum not in num_list:
                num_list.add(inum)

    # Convert to list and sort
    num_list = list(num_list)
    num_list.sort(reverse=True)

    for num in num_list:
        print('Checking ' + str(num))
        if probablyPrime(num,100):
            print('\n' + str(num) + ' is probably the largest prime!')
            return

largestPrime(num)

提高速度的另一种方法可能是python的multiprocessing包。

答案 2 :(得分:0)

<强>代码:

def isprime(n):
    if n == 2:
        return str(n)+" is the biggest prime"
    if n % 2 == 0:
        return isprime(n-1) #not prime, check again for next biggest number
    max = n**0.5+1
    i = 3
    while i <= max:
        if n % i == 0:
            return isprime(n-1) #not prime, check again for next biggest number
        i+=2
    return str(n)+" is the biggest prime"

print "Testing 7:",isprime(7)
print "Testing 23:",isprime(23)
print "Testing 2245:",isprime(2245)
print "Testing 222457:",isprime(222457)
print "Testing 727245628:",isprime(727245628)

<强>输出:

>>> 
Testing 7: 7 is the biggest prime
Testing 23: 23 is the biggest prime
Testing 2245: 2243 is the biggest prime
Testing 222457: 222437 is the biggest prime
Testing 727245628: 727245613 is the biggest prime