在进行任何详细的测试之前,我们可以消除所有偶数x值(除了2),因为我们可以简单地判断它们不是素数。在
一个小的改进是只调用str(x)一次,以后再重用该值。在
我们可以利用所有偶数长度回文都是11的倍数,这意味着(除了11本身)它们不是素数。我们可以跳到下一个奇数长度x值。在
因为我们已经消除了偶数,我们的素数测试只需要测试奇数除数。此外,我们可以在到达sqrt(x)时停止循环,而不是一直到x本身。在
最后,不需要使用布尔标志变量将素数从循环中取出。如果我们不break,则附加到循环的else块将运行。在
代码:import math
def next_prime_palindrome(x):
while True:
x += 1
if x > 2 and x % 2 == 0: # even numbers greater than 2 are non-prime
continue
s = str(x) # compute str(x) just once
if x > 11 and len(s) % 2 == 0: # all even-length palindromes are multiples of 11
x = 10 ** len(s) # so jump to the next odd-length integer
continue
if s != s[::-1]: # palindrome test
continue
for i in xrange(3, round(math.sqrt(x))+1, 2): # loop over odd potential divisors
if x % i == 0: # prime test
break
else: # this else block runs only if no break happened in the loop, so x is prime
return x
下面是一些运行的测试,显示了一些优化可以节省大量时间的情况:
^{pr2}$
进一步的改进可能是直接生成回文,而不是从整数开始,再做回文测试来过滤它们。那会比你原来的设计要远一点,所以我把它留给别人。在