在 Internet 上流传的许多质数测试中,请考虑以下 Python 函数:
def is_prime(n):
if n == 2 or n == 3: return True
if n < 2 or n%2 == 0: return False
if n < 9: return True
if n%3 == 0: return False
r = int(n**0.5)
# since all primes > 3 are of the form 6n ± 1
# start with f=5 (which is prime)
# and test f, f+2 for being prime
# then loop by 6.
f = 5
while f <= r:
print('\t',f)
if n % f == 0: return False
if n % (f+2) == 0: return False
f += 6
return True
由于所有大于 3 的素数都是 6n ± 1 的形式,因此一旦我们消除它n
:
- 不是 2 或 3(它们是素数)和
- 甚至 (with
n%2
) 和
- 不能被 3 整除(用
n%3
),那么我们可以每 6 个 n ± 1 进行一次测试。
考虑素数 5003:
print is_prime(5003)
印刷:
5
11
17
23
29
35
41
47
53
59
65
True
该行r = int(n**0.5)
计算为 70(5003 的平方根为 70.7318881411 并int()
截断该值)
考虑下一个奇数(因为除了 2 之外的所有偶数都不是素数)5005,同样的打印结果:
5
False
极限是平方根,因为x*y == y*x
该函数只需循环 1 次即可发现 5005 可被 5 整除,因此不是素数。因为5 X 1001 == 1001 X 5
(并且两者都是 5005),我们不需要在循环中一直走到 1001 来知道我们在 5 处知道的内容!
现在,让我们看看您拥有的算法:
def isPrime(n):
for i in range(2, int(n**0.5)+1):
if n % i == 0:
return False
return True
有两个问题:
- 它不测试是否
n
小于 2,并且没有小于 2 的素数;
- 它测试 2 到 n**0.5 之间的每个数字,包括所有偶数和所有奇数。由于每个大于 2 且能被 2 整除的数都不是素数,因此我们可以通过只测试大于 2 的奇数来加快速度。
所以:
def isPrime2(n):
if n==2 or n==3: return True
if n%2==0 or n<2: return False
for i in range(3, int(n**0.5)+1, 2): # only odd numbers
if n%i==0:
return False
return True
好的——它加快了大约 30%(我对它进行了基准测试......)
我使用的算法is_prime
仍然快 2 倍左右,因为只有每 6 个整数在循环中循环。(再一次,我对它进行了基准测试。)
旁注:x**0.5 是平方根:
>>> import math
>>> math.sqrt(100)==100**0.5
True
旁注 2:素数测试是计算机科学中一个有趣的问题。