【问题标题】:How to create the most compact mapping n → isprime(n) up to a limit N?在Python中检查一个数字是否是素数[重复]
【发布时间】:2011-05-06 01:51:00
【问题描述】:

我写了以下代码,它应该检查输入的数字是否是质数,但是有一个问题我无法通过:

def main():
    n = input("Please enter a number:")
    is_prime(n)

def is_prime(a):
    x = True
    for i in (2, a):
            while x:
               if a%i == 0:
                   x = False
               else:
                   x = True


    if x:
        print("prime")
    else:
        print("not prime")

main()

如果输入的数字不是质数,它应该显示“非质数”,但如果数字是质数,它不会显示任何内容。我该如何解决这个问题?

【问题讨论】:

  • 注意:for i in (2, a) 恰好运行循环两次:一次使用 i == 2,一次使用 i == a。您可能想使用for i in range(2, a)

标签: python primes


【解决方案1】:

检查数字 N 是否为素数的一个非常简单明了的蛮力解决方案:只需检查从 2 到 N 的平方根之间是否存在 N 的除数(如果有兴趣,请参阅为什么 here)。

以下代码同时兼容 Python 2 和 Python 3:

from math import sqrt
from itertools import count, islice

def is_prime(n):
    return n > 1 and all(n % i for i in islice(count(2), int(sqrt(n) - 1)))

这是一个更简单的仅 Python 3 实现:

def is_prime(n):
    return n > 1 and all(n % i for i in range(2, int(n ** 0.5) + 1))

为了清楚起见,这里是上述的扩展版本:

from math import sqrt
from itertools import count, islice

def is_prime(n):
    if n < 2:
        return False

    for divisor in islice(count(2), int(sqrt(n) - 1)):
        if n % divisor == 0:
            return False

    return True
def is_prime(n):
    if n < 2:
        return False

    for divisor in range(2, int(n ** 0.5) + 1):
        if n % divisor == 0:
            return False

    return True

这并不意味着任何接近最快或最优的素数检查算法,它只是实现了简单和简洁的目标,这也减少了实现错误。它的时间复杂度为O(sqrt(n))

如果您正在寻找更快的算法来检查数字是否为素数,您可能会对以下内容感兴趣:


实施说明

您可能已经注意到,在与 Python 2 兼容的实现中,我将itertools.count()itertools.islice() 结合使用,而不是简单的range()xrange()(旧的Python 2 生成器范围,在 Python 3 中是默认值)。这是因为在 CPython 2 xrange(N) 中,对于某些 N 使得 N > 263 ‒ 1 (或 N > 231 ‒ 1 取决于实现)引发一个 @ 987654341@。这是一个不幸的 CPython 实现细节。

我们可以使用itertools 来解决这个问题。由于我们使用itertools.count(2)2 计数到无穷大,所以在sqrt(n) - 1 步骤之后我们将达到sqrt(n),我们可以使用itertools.islice() 限制生成器。

【讨论】:

  • 某些情况会失败...我猜在 for 循环中结束限制应该是 sqrt(n)+1 而不是 sqrt(n)-1
  • @Katie 这已经被纠正了(可能是几年前,不记得什么时候了)。我已经测试了上面的代码,它适用于 1
【解决方案2】:

有很多有效的方法可以测试素数(这不是其中之一),但是您编写的循环可以用 Python 简洁地重写:

def is_prime(a):
    return all(a % i for i in xrange(2, a))

也就是说,如果 2 和 a(不包括)之间的所有数字在除以 a 时给出非零余数,则 a 是素数。

【讨论】:

  • 请注意,is_prime 针对 0 和 1 返回 True。但是,Wikipedia defines a prime number 是“大于 1 的自然数,除了 1 和自身之外没有正除数。”所以我把它改成了return a &gt; 1 and all(a % i for i in xrange(2, a))
  • 请勿使用此功能!原因如下。 1) 如果 a == 1,则返回 true,但 1 不被视为素数。 2) 它检查一个数字在 a - 1 之前是否为素数,但一个体面的程序员知道它只需要到 sqrt(a)。 3)它不跳过偶数:除了2,所有素数都是奇数。 4) 它没有展示如何找到素数背后的算法思想,因为它使用了 Python 的商品。 5) xrange 在 Python 3 中不存在,所以有些人将无法运行它。
【解决方案3】:

如果您只有几个查询,这是查看一个数字是否为素数的最有效方法。如果您询问很多数字是否为素数,请尝试Sieve of Eratosthenes

import math

def is_prime(n):
    if n == 2:
        return True
    if n % 2 == 0 or n <= 1:
        return False

    sqr = int(math.sqrt(n)) + 1

    for divisor in range(3, sqr, 2):
        if n % divisor == 0:
            return False
    return True

【讨论】:

    【解决方案4】:

    如果a 是素数,那么代码中的while x: 将永远运行,因为x 将保持True

    那为什么while 在那里?

    我认为你想在找到一个因素时结束 for 循环,但不知道如何,所以你添加了 while,因为它有一个条件。所以这是你的做法:

    def is_prime(a):
        x = True 
        for i in range(2, a):
           if a%i == 0:
               x = False
               break # ends the for loop
           # no else block because it does nothing ...
    
    
        if x:
            print "prime"
        else:
            print "not prime"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-17
      • 2012-10-08
      • 2015-09-15
      • 1970-01-01
      • 2016-08-21
      • 1970-01-01
      • 2020-07-19
      相关资源
      最近更新 更多