质数(Prime number)又称素数, 质数是大于并且只能被
和自身整除的天然数。大于
的天然数若是不是素数,就称为合数(Composite number)。python
算术基本定理最先由欧几里得证实, 是表示任何合数均可以不断分解成素数的组合,如能够分解为
两个素数,欧几里得发现把这些素数因子的次方相乘能够获得原来的数字
,并且这种分解为素数乘积的方式是惟一的。素数因子分解就像是一个锁,并且只有一把开锁的钥匙,这也是现代密码学的基础。面试
素数定理描述素数在天然数中分布的渐进状况,就是小于中素数的个数随着
的增大素数的密度就愈来愈小。当
愈来愈大时它的图像就愈来愈接近
。因此一个数字内素数的数量
约等于
,当
越大时偏差越小。因此好比要生成
大小的素数序列,使用这个方法的话就要提升反推出来上界
的大小。app
那么怎么判断一个数是否是素数?这也是不少面试题里面问到的。一种简单的方法是试除法。dom
好比判断是否是素数,可让
除以
到
之间的整数,若是能够除尽则表示是合数不然是质数。测试
def isPrime(n):
if n < 2: return False
for i in range(2, n):
if n % i == 0:
return False
return True
复制代码
可是能够发现大于偶数都不是质数,由于它们能够被
整除,因此这能够减小迭代次数。ui
def isPrime(n):
if n == 2: return True
if n < 2 or n % 2 == 0: return False
for i in range(3,n,2):
if n % i == 0:
return False
return True
复制代码
还有没有更快的方法?有,就是迭代到,由于一个数字分解为两个因子,其中必然有一个小于或等于
,否则两个都大于
它们相乘就大于
了。spa
def isPrime(n):
if n == 2: return True
if n < 2 or n % 2 == 0: return False
for i in range(3, int(n ** 0.5) + 1, 2):
if n % i == 0:
return False
return True
复制代码
试除法还能不能更快?根据算术基本定理任何合数最终均可以分解为素数的组合,因此只用除小于的素数就好了。.net
筛选法(sieve of Eratosthenes)能够给出小于的素数序列,好比要生成
内的素数序列,首先能够生成2到100间数字表,而后将列表第一个没被标记的数字标记为素数而后将数字表中它的倍数标记为合数,而后不断重复这个步骤。3d
对于给定只须要遍历到
,剩下的就都是素数了。code
def sieve(n):
composite = {}
primes = [2]
for i in range(3, int(n ** 0.5) + 1, 2):
if i not in composite:
for j in range(i ** 2, n + 1, i): composite[j] = 1
for k in range(3, n + 1, 2):
if k not in composite: primes.append(k)
return primes
复制代码
对于不指定的大小能够这么写。
def genPrimes():
primes = [2]
i = 1
yield 2
while True:
i += 2
for p in primes:
if i % p == 0:
break
else:
primes.append(i)
yield i
复制代码
虽然通常判断是否是素数用试除法
就好了,可是当要判断一个大数是否是素数时,也仍是太慢了。
费马小定理
是欧拉定理的一个特殊状况,它是说一个正整数的
质数
次方减
能够被
次方整除。用公式表示能够为
。
可是也不能彻底正确,好比 可是
,因此能够随机生成多个
来测试,这样就能够下降将出错几率。
import random
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def randA(p):
return random.randint(1, p - 1)
def fastMod(f, p, m):
ans = 1
whlie p > 0:
if p % 2 == 1:
ans = (ans * f) % m
p -= 1
p //= 2
f = (f ** 2) % m
return ans
def isPrime(p):
trials = 30
for i in range(trials):
a = randA(p)
if gcd(a, p) != 1: return False
if fastMod(a, p - 1, p) != 1: return False
return True
复制代码