如果您想主要坚持当前的代码但改进细节:
- 使用
for i in range(3, ...,因为您知道素数对不能以 1 或 2 开头。然后您可以删除 if i <= 2...,因为这永远不会发生。
- 拥有一个同时测试两个数字的素数的
is_prime_pair 函数让事情变得更加困难。而是有一个 is_prime 函数来测试一个数字,然后调用 is_prime(i) and is_prime(i+2)。
- 很明显,如果
x 不大于max_div,那么它小于i 和i2,所以删除or x == i or x == i2。顺便说一句,if (x > max_div or x == i or x == i2): 不需要那些额外的括号:if x > max_div or x == i or x == i2: 是有效的。
- 如果
x == max_div,那么您已经可以break,因为max_div 大于x 的平方根。
-
** 优先于 +,因此简化为 max_div = i2 ** 0.5 + 1。
所以现在我们有:
def is_prime(i):
max_div = i ** 0.5 + 1
for x in k:
if x >= max_div:
break
...
这是一种愚蠢的做事方式:只需遍历max_div 为上限的范围!您只需将 max_div 转换为 int 即可在 range 函数中使用。说服自己,无论i 是否是一个完美的正方形,这都是正确的,并且没有一个错误的错误。然后我们有:
def is_prime(i):
max_div = int(i ** 0.5 + 1)
for x in range(3, max_div, 2):
if i % x == 0:
return False
return True
这是一种可以在 Python 中方便地重构的常见模式:
def is_prime(i):
max_div = int(i ** 0.5 + 1)
return not any(i % x == 0 for x in range(3, max_div, 2))
(如果您不熟悉,我使用了generator expression)
您可以通过两个技巧使其更简洁,尽管可能更难阅读。首先内联max_div,因为它只使用过一次。然后,您可以使用all 代替any,并将整数视为布尔值:
def is_prime(i):
return all(i % x for x in range(3, int(i ** 0.5 + 1), 2))
这里我们说一个数是素数,如果它除以x 时留下一些非零余数对于所有x(因此all 函数)值得检查。这是因为在 Python 中0 类似于False 而所有其他数字都类似于True。
正如我在其他答案中提到的,无需手动格式化该对。
由于您使用print 作为语句,因此您必须使用 Python 2,而不是标签上所说的 3。在这种情况下,将所有 range 实例替换为 xrange 以提高效率。
所以最后就是:
n = 100 # upper limit number
def is_prime(i):
return all(i % x for x in xrange(3, int(i ** 0.5 + 1), 2))
for i in xrange(3, n + 1, 2):
if is_prime(i) and is_prime(i + 2):
print (i, i + 2)
但是我相信我的其他答案会更快,尽管这可能不会仅针对 n = 100 显示。最明显的问题是,只要i 是素数,那么is_prime(i + 2) 将被调用,然后在循环的下一次迭代中is_prime(i) 将是多余的,因为这是刚刚计算的。您可以通过使用集合记住 is_prime 来改进这一点。