在Python中检查一个数字是不是是素数[重复]

Posted

技术标签:

【中文标题】在Python中检查一个数字是不是是素数[重复]【英文标题】: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) 【参考方案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))

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

Finding primes & proving primality:对最著名的素性检验及其历史的简要概述和解释。 Probabilistic primality tests (Wikipedia):这些可以很容易地合并到上面的代码中,如果它们没有通过,可以很容易地跳过蛮力,例如这个问题的副本有this excellent answer。 Fast deterministic primaliry tests (Wikipedia) 此问答Fastest way to list all primes below N 以及pyprimesieve 库。

实施说明

您可能已经注意到,在与 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"

【讨论】:

以上是关于在Python中检查一个数字是不是是素数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在python中检查字符串是不是为数字[重复]

检查数字是不是为素数

筛素数

python 检查数字是否为素数

如何检查我的 python 对象是不是为数字? [复制]

检查python列表中是不是已经存在一个数字