在Python中打印100以下的所有双素数对

时间:2016-03-24 00:29:02

标签: python python-3.x primes

编写程序以确定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

如何优化代码以缩短代码?

4 个答案:

答案 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)

如果您想要坚持使用当前的代码,但要改进细节:

  1. 使用for i in range(3, ...,因为您知道素数对不能以1或2开头。然后您可以删除if i <= 2...,因为这绝不会发生。
  2. 这使得is_prime_pair函数更难以同时测试两个数字的素数。而是使用is_prime函数测试单个数字,然后调用is_prime(i) and is_prime(i+2)
  3. 很明显,如果x不大于max_div,那么它会小于ii2,因此请移除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:有效。
  4. 如果x == max_div那么您可以break因为max_div大于x的平方根。
  5. **优先于+,因此简化为max_div = i2 ** 0.5 + 1
  6. 现在我们有:

    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来改进这一点。