【问题标题】:Calculating Primes and Appending to a List计算素数并附加到列表
【发布时间】:2018-01-08 16:32:55
【问题描述】:

我最近开始尝试使用 python 解决 Euler 项目中的问题,并且在尝试计算素数并将它们附加到列表时遇到了这个问题。我已经编写了以下代码,但是我很困惑为什么我运行它时它没有输出任何东西。

import math

primes = []

def isPrime(i):
    if number<=1:
        return False
    if number==2:
        return True
    if number%2==0:
        return False
    for i in range(3,int(sqrt(number))+1):
        if number%i==0:
            return False
    return True

for i in range (1, 9999999):
    if isPrime(i) == True:
        primes.append(i)
    else:
        continue
print(primes)

【问题讨论】:

  • 开始将def isPrime(i): 更改为def isPrime(number):for i in range(3,int(sqrt(number))+1): 更改为for i in range(3,int(math.sqrt(number))+1):
  • 这是一种非常低效的计算素数列表的方法。最好直接用筛子生成素数。
  • Mh... 它还能运行吗? i 应该是 numbersqrt 应该是 math.sqrt
  • 当你在 Python 中使用 for 循环时,你几乎肯定做错了。 Python 方法是使用列表推导:primes = [i for i in range (1, 9999999) if isPrime(i)].
  • 你说的很对@DYZ,这正是我要评论的,因为它比附加到空列表和更简洁的语句更有效

标签: python list primes


【解决方案1】:

试试:

import math

primes = []

def isPrime(number):
    if number<=1:
        return False
    if number==2:
        return True
    if number%2==0:
        return False
    for i in range(3,int(math.sqrt(number))+1):
        if number%i==0:
            return False
    return True

for i in range (1, 9999999):
    if isPrime(i) == True:
        primes.append(i)

print(primes)

【讨论】:

  • 不需要:else: continue
  • 固定@AndreaCorbellini。
【解决方案2】:

试试这个:

import math

primes = []

def isPrime(number):
    if number<=1:
        return False
    if number==2:
        return True
    if number%2==0:
        return False
    for ind in range(3,int(math.sqrt(number))+1):
        if number%ind==0:
            return False
    return True

for i in range (1, 100):
    if isPrime(i) == True:
        primes.append(i)
    else:
        continue

print(primes)

为了显示它有效,我打印了前 100 个:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

【讨论】:

    【解决方案3】:

    使用条件列表推导:

    primes = [
        i for i in range(1, 9999999) 
        if i == 2 
        or i > 2  # Anything less than 2 is not prime.
        and i % 2  # No evens (except for 2 above)
        and all(i % n for n in range(3, int(i ** 0.5) + 1))]
    
    >>> primes[:10]
    [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
    
    >>> primes[-10:]
    [9999889,
     9999901,
     9999907,
     9999929,
     9999931,
     9999937,
     9999943,
     9999971,
     9999973,
     9999991]
    

    【讨论】:

      【解决方案4】:

      最简单的方法是使用一种叫做筛子的东西。以下是如何使所有素数达到一百万。

      def mark_sieve(sieve, x):
          for i in range(x+x, len(sieve), x):
              sieve[i] = False
      
      sieve = [True]*(10**7+1)
      for x in range(2, int(len(sieve)**0.5 + 1)):
          if sieve[x]: mark_sieve(sieve, x)
      

      我们的想法是,我们最初创建一个名为sieve 的列表并将所有值分配给True,这意味着我们现在将所有数字视为100 万(含)作为质数。我们将遍历每个数字到一百万,并将它的每个倍数标记为Falsesieve 列表中。此外,为了优化,我们只迭代到 100 万的平方根。为什么这样?因为一个数字不可能有两个因子都大于该数字的平方根。因此,如果我们将一个数除以整数,直到它的平方根的上限仍然不可整除,这意味着它是一个素数。

      所以如果你想检查一个数字是否是素数,你可以简单地使用sieve[some_number]。如果它返回 False 它不是素数。要获取素数列表,您可以使用[x for x in range(len(sieve)) if sieve[x]]

      编辑 速度比较 -

      import timeit
      import math
      
      def isPrime(number):
          if number<=1:
              return False
          if number==2:
              return True
          if number%2==0:
              return False
          for ind in range(3,int(math.sqrt(number))+1):
              if number%ind==0:
                  return False
          return True
      
      def mark_sieve(sieve, x):
          for i in range(x+x, len(sieve), x):
              sieve[i] = False
      
      
      # Other approaches
      time_0 = timeit.default_timer()
      primes = []
      for i in range (1, 10**6+1):
          if isPrime(i) == True:
              primes.append(i)
          else:
              continue
      
      # Sieve Approach
      time_1 = timeit.default_timer()
      sieve = [True]*(10**6+1)
      sieve[0] = False #because we wont consider zero and one as primes
      sieve[1] = False
      for x in range(2, int(len(sieve)**0.5 + 1)):
          if sieve[x]: mark_sieve(sieve, x)
      
      primes_2 = [x for x in range(len(sieve)) if sieve[x]]
      
      time_2 = timeit.default_timer()
      time_1-time_0 # 12.423080921173096 seconds
      time_2-time_1 # 0.9901950359344482 seconds
      

      对于 10 万个数字,使用筛子的速度要快 12 倍以上。对于一百万,该比率变为 90。此外,当使用这么多数字时,我建议不要附加列表。相反,启动一个列表,然后分配值。

      【讨论】:

      • 与其他方法相比,这种方法速度惊人。但是,它可以在边缘使用一点点清理,因为它声称 0 和 1 是素数...
      • @cdlane,是的,我跳过了。进行了更改。谢谢!
      【解决方案5】:

      如果您正在构建一个素数列表,则将该列表用作解决方案的一部分会更有效。

      例如这个循环:

      for i in range(3, int(math.sqrt(number)) + 1):
      

      对于素数 1009 将测试大约 30 个数字,但实际需要测试的只有比 1009 的平方根少 10 个素数。而且这种差异还在不断扩大。

      使用我们不断增长的主要列表作为解决方案的一部分:

      primes = [2]
      
      for number in range(3, 9999999 + 1, 2):  # only test odd numbers
      
          for prime in primes:
              if prime * prime > number:  # we're past sqrt, a prime!
                  primes.append(number)
                  break
      
              if number % prime == 0:  # a composite
                  break
      
      print(*primes[:10], '...', *primes[-10:])
      

      没有任何地方比 @ClockSlave 的筛子快,但可能会在许多其他解决方案之前完成。

      【讨论】:

        【解决方案6】:

        现在可以了,我已将数字缩短为 999

        import math
        
        primes = []
        
        
        def isPrime(number):
            if number <= 1:
                return False
            for i in range(2, int(math.sqrt(number)) + 1):
                if number % i == 0:
                    return False
            return True
        
        for i in range(1, 999):
            if isPrime(i):
                primes.append(i)
        
        print(primes)
        

        [输出]:

        [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227、229、233、239、241、251、257、263、269、271、277、281、283、293、307、311、313、317、331、337、347、349、353、359、367、 373、379、383、389、397、401、409、419、421、431、433、439、443、449、457、461、463、467、479、487、491、499、503、509、521、 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683、691、701、709、719、727、733、739、743、751、757、761、769、773、787、797、809、811、821、823、827、829、839、853、857、 859、863、877、881、883、887、907、911、919、929、937、941、947、953、967、971、977、983、991、997]

        【讨论】:

          【解决方案7】:

          您获取 [0,9999999] 中所有素数的算法效率不高。它需要花费很长时间才能执行,以便在执行时看不到输出。只是因为它还没有完成。如需更快的算法,您可以查看this

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-11
            • 2021-09-17
            • 1970-01-01
            • 2020-09-05
            相关资源
            最近更新 更多