【问题标题】:How to print prime numbers in python without using for loop and while loop如何在python中打印素数而不使用for循环和while循环
【发布时间】:2018-05-06 12:09:53
【问题描述】:

我尝试过的:

for num in range(2,50):
    prime = True
    for i in range(2,num):
        if (num%i==0):
            prime = False
    if prime:
       print (num)

结果很好,但禁止以任何方式使用 for 或 while 循环,所以有没有其他方法可以在不使用 for 或 while 循环的情况下做到这一点?

【问题讨论】:

  • 所以for num in range(2,50): 循环也不允许?
  • 您能否提供一些有关“禁止”的背景信息,以便我们了解此要求背后的基本原理?
  • 你只是想得到一个具有一定范围的素数吗?
  • 你不能做一个递归函数吗?

标签: python python-3.x loops primes


【解决方案1】:

这很愚蠢,但它确实有效,所以也许它至少会给你一些想法:

print(list(filter(lambda x: not list(filter(lambda y:x%y == 0, range(2,x))), range(2, 50))))

输出:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

【讨论】:

  • 不笨......但它证明你知道python使用内置函数......更好的方法
【解决方案2】:

有没有其他方法可以在不使用 for 或 while 循环的情况下做到这一点?

是的,您可以使用递归函数:

def prime_number(n, d):
    if n//2 < d:
      return True
    if n%d == 0:
      return False
    return prime_number(n, d+1)

def find_primes(n,i, result):
  if i == n + 1:
    return result
  if prime_number(i, 2):
    result.append(i)
  return find_primes(n, i+1, result)

print(find_primes(100,2, []))

输出

[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]

此外,您可以使用list comprehension 简化for loops

primes = [n for n in range(2, 50) if all(n % d for d in range(2, n))]

【讨论】:

  • 当使用 Python 的默认堆栈大小时,这会在find_primes(672, 2, []) 以上遇到麻烦。我发布了一个替代实现,它只将该限制提高了 3 倍。
【解决方案3】:

这是Sieve of Eratosthenes 的递归实现。它使用扩展切片分配来执行主要的筛分步骤。它会因RecursionError 在大数上失败,但使用默认设置它可以安全地计算高达 990000 左右的素数。它不如此代码的更常见的迭代版本快,但比进行简单的蛮力因子搜索要快得多。

def rsieve(i, num, stop, seq):
    if i == stop:
        return
    if seq[i]:
        seq[i*i : num : i] = [False] * (1 + (num - 1)//i - i)
    rsieve(i + 1, num, stop, seq)

def primes(num):
    seq = [True] * num
    seq[:2] = [False] * 2
    rsieve(2, num, int(num ** 0.5) + 1, seq)
    return filter(lambda i: seq[i], range(num))

# Test
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

FWIW,您可以通过将lambda 函数参数替换为filter 直接调用seq.__getitem__“魔术”方法,使这段代码的运行速度几乎提高一倍。也就是说,

return filter(seq.__getitem__, range(num))

直接调用“魔术”方法通常被认为是不好的做法,因此请不要这样做,除非您了解自己在做什么。 ;)

【讨论】:

    【解决方案4】:

    这是我对@MihaiAlexandru-Ionut 解决方案的返工,通过消除偶数的质数测试并在平方根而不是 1/2 处停止质数测试,在运行与 Python 的默认堆栈大小发生冲突之前,该解决方案可以计算高 3 倍目标:

    def find_primes(n, i=2):
    
        primes = []
    
        if i > n:
            return primes
    
        def is_odd_prime(n, d=3):
            if n < d * d:
                return True
    
            if n % d == 0:
                return False
    
            return is_odd_prime(n, d + 2)
    
        multi = i != 2
    
        if not multi or is_odd_prime(i):
            primes.append(i)
    
        return primes + find_primes(n, i + 1 + multi)
    
    print(find_primes(1960))
    

    @PM2Ring 的筛子解决方案的(堆栈)效率仍然远远不够!

    【讨论】:

      【解决方案5】:

      这将为您提供不超过 t 的所有素数,无需使用外部库或 for/while 循环。

      t=1000
      
      a=set(range(2,t))
      l=map(lambda c:range(2*c,t,c),a)
      result=a.difference(*l)
      
      print(sorted(result))
      

      也不算太慢:

      >>> Calculating primes up to 1 took 2.599999999997049e-05 seconds
      >>> Calculating primes up to 10 took 4.6000000000101515e-05 seconds
      >>> Calculating primes up to 100 took 0.00015300000000006975 seconds
      >>> Calculating primes up to 1000 took 0.001670999999999978 seconds
      >>> Calculating primes up to 10000 took 0.023809999999999998 seconds
      >>> Calculating primes up to 100000 took 0.24447599999999992 seconds
      >>> Calculating primes up to 1000000 took 3.301934 seconds
      >>> Calculating primes up to 10000000 took 42.691604 seconds
      

      使用 100000000 产生内存错误

      【讨论】:

        【解决方案6】:

        这解决了打印一个列表,一次一个数字,每个在新行上 - 没有for loop

        print( *[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47], sep = '\n')
        

        输出:

        2
        3
        5
        7
        11
        13
        17
        19
        23
        29
        31
        37
        41
        43
        47
        

        所有素数不超过 50 - 不涉及 for 循环。


        至于素数列表,我通过硬编码来欺骗它们(你没有询问创建,只是打印 - 尽管你的代码试图创建它们)。

        如果您有兴趣高效地创建它们,我建议您搜索 SO - f.e.你找到Fastest way to list all primes below N

        【讨论】:

        • 为什么投反对票?这个问题没有说明计算素数。
        猜你喜欢
        • 2018-07-30
        • 1970-01-01
        • 1970-01-01
        • 2011-10-06
        • 2020-08-14
        • 2021-10-12
        • 1970-01-01
        • 2018-04-20
        • 2012-12-07
        相关资源
        最近更新 更多