在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 > 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中检查一个数字是不是是素数[重复]的主要内容,如果未能解决你的问题,请参考以下文章