编写程序以确定100以下有多少双素数对
n = 100 # upper limit number
k = range(3, int((n+1)**0.5) + 1, 2)
def is_prime_pair(i, i2):
if i <= 2 or i2 <= 2:
return False
max_div = (i2 ** 0.5) + 1
for x in k:
if (x > max_div or x == i or x == i2):
break
if (i % x == 0) or (i2 % x == 0):
return False
return True
for i in range(1, n+1, 2):
if is_prime_pair(i, i+2):
print "(" + str(i) + ", " + str(i+2) + ")" # Print pairs if prime pair
如何优化代码以缩短代码?
答案 0 :(得分:1)
如何优化代码以使其更短更快?
基于筛选的方法更短,速度更快:
def find_prime_pairs(n):
sieve = [True] * n
if n > 0:
sieve[0] = False
if n > 1:
sieve[1] = False
for number in range(2, int(n ** 0.5) + 1):
if sieve[number]:
for index in range(number * number, n, number):
sieve[index] = False
return [(a, b) for b, a in enumerate(range(0, n - 2), start=2) if sieve[a] and sieve[b]]
print(*find_prime_pairs(100), sep='\n')
<强> USAGE 强>
> python3 test.py
(3, 5)
(5, 7)
(11, 13)
(17, 19)
(29, 31)
(41, 43)
(59, 61)
(71, 73)
>
使用高达100的素数时,任何代码都会执行,它的范围太小,无法提高性能。让我们考虑1000000(百万)。出于计时目的,我们将计算而不是打印成对。
@AlexHall提供的第一个答案需要原始代码的两倍,才能将对数计算到一百万。他的第二个答案比原始代码长三倍。较短并不总是意味着更快。在您对其进行全面测试之前,请不要相信任何答案。
我上面的基于筛选的代码比原始代码快4倍,而且小15%。
答案 1 :(得分:1)
def prime(i):
""" This function finds whether a number is prime or not?"""
val=False
for n in range(2,i):
if i%n==0:
break;
else:
val=True
return val
for x in range(2,1000):
if prime(x)==True & prime(x+2)==True:
print("{} and {} are prime twins".format(x,x+2))
这应该有所帮助。首先,我定义一个函数是否为素数。接下来,我通过将该函数与x和x + 2进行比较,使用该函数查找一个范围内的双素数。 x是该范围内的每个数字。
答案 2 :(得分:0)
首先建立一个素数列表,然后搜索双胞胎 这样你就不会两次检查相同的数字作为素数。
primes = [2]
for candidate in xrange(3, 100, 2):
# Secondly don't try dividing potential primes by every odd number
# Just try dividing by the primes you already know!
for prime in primes:
if prime ** 2 > candidate:
primes.append(candidate)
break
if candidate % prime == 0:
break
# Iterate through all positions in the list except the last to avoid an IndexError
for i in xrange(len(primes) - 1):
if primes[i + 1] - primes[i] == 2:
print (primes[i], primes[i + 1])
元组按照您希望的方式进行格式化。
答案 3 :(得分:0)
如果您想要坚持使用当前的代码,但要改进细节:
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
即可。相信自己这是正确的,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
,因为它只使用一次。然后,代替any
,您可以使用all
并将整数视为布尔值:
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
来改进这一点。