【发布时间】:2014-01-16 02:41:20
【问题描述】:
对于这个问题,我需要在一个较大的数字中找到最大的质数。出于示例的目的,假设较大的数字是“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()
我很确定这段代码给出了正确的答案,但正如我所说,它真的很慢。谁能帮我弄清楚如何加快速度?
感谢您的帮助!
【问题讨论】:
-
一个明显的改进:将
if isPrime...if > largest重新排列为if >largest...if isPrime,因此您只检查它是否是质数,如果它大于您迄今为止找到的最大质数(如果它更小,您不会'不在乎它是否是素数)。 -
有许多主要测试算法比您编写的幼稚算法更有效。特别是如果你可以接受误报——你可以;您所要做的就是保留最大的“可能是素数”数字的排序列表,然后最后对最大的数字进行缓慢但保证正确的测试。当然,您需要做一些研究来选择最适合您需求的算法。
-
您的主要检测算法是主要瓶颈。仅用他的算法找出整个 10000 位数字是否是素数就需要一段时间。查看en.wikipedia.org/wiki/Primality_test 以获得更好的测试。
-
附带说明,以
largest=2开头是一个非常小的优化,考虑到这意味着您可能会得到不正确的值(例如,在100000000000上尝试...),我不知道觉得值得。 -
最后,在一堆算术上做一个紧密的循环正是 Python 不擅长的。如果可能的话,您想将内部循环(
isPrime)推入 C 中。通过在 Cython 中编写它很容易做到这一点。或者,有一些巧妙的方法可以将大量数字的算术转换为 numpy 数组的矢量化算术。或者只是在 PyPy 而不是 CPython 中运行您的代码——有时(并且每个版本更常见)它会设法将您的代码 JIT 到合理的速度。但是,在您获得 ZPP 或类似的易于处理的算法之前,请不要担心这一点。
标签: python performance optimization