一、什么是素数?
素数又称为质数。素数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。素数在日常中最多的应用就是加密算法,例如RSA加密算法就是基于来实现的。RSA算法会随机生成两个1024位的质数相乘,要破解密码必须对乘积做质因数分解,而1024位的质因数分解是非常困难的。
二、如何快速的算出小于某个数的所有素数?
从素数的概念上似乎可以很快得出一个算素数的公式,即将一个数循环做除法,从1一直除到它本身,如果中途只有被1和自己整除了这个数便是素数了,这样的计算效率是非常差的,因为他会不停的遍历整个数据范围。我们来试着跑一下它的效率:
#求10万以内的素数 import datetime start = datetime.datetime.now() for i in range(2,100000): for j in range(2,i): if i%j == 0: break #else: #print(i) stop = datetime.datetime.now() print(stop-start)
运行结果: 0:01:04.326679 ,在没有print的情况下竟然用了1分多钟,并且数字越大计算越慢。这样的效率肯定是不被允许的。下面介绍一种最常见的质数算法的原理:
三、埃拉托色尼素数筛选法
埃拉托色尼是一名古希腊的地理学家,他是世界上第一个计算出地球周长的人。埃拉托色尼素数筛选法可以很快速的计算出1到N之间的所有素数。将n开根号,即N^0.5,去掉2到N^0.5中所有素数的倍数,剩下的数便都是素数了。例如求1到25中的素数有哪些,第一步是将25开根号,得到5;第二步将2到5的素数取出来,分别是2、3、5;再将2到25中且是2、3、5的倍数的数去掉,即去掉4、6、8、9、10、12、14、15、16、18、20、21、22、24、25,剩下2、3、5、7、11、13、17、19便是1到25中的所有素数了。
这里还用到了一个数学知识,即只要小于或等于根号N的数(1除外)不能整除N,则N一定是素数;反过来说就是只要小于或等于根号N的数(1除外)能整除N,则N一定是合数。下面给出证明过程:
假设一个数N是合适,那一定存在一个因数b和一个非1且非自身的因数a,即a*b=N
等式两边同时开根号得出:(a*b)^0.5=a^0.5*b^0.5=N^0.5
可以推出:若N为合数,则a和b中一定有一个大于或等于N^0.5,另一个小于或等于N^0.5
按照这个结论,就只需计算小于等于N^0.5的数了,这样就大大提高了效率(要注意等于N^0.5的这个边界):
#求10万以内的素数 import datetime start = datetime.datetime.now() for i in range(2,100000): for j in range(2,int(i**0.5+1)): #边界需要加1 if i%j == 0: break #else: #print(i) stop = datetime.datetime.now() print(stop-start)
运行结果: 0:00:00.428024 。可以说是质的飞跃。
小的优化
我们也可以将偶数事先就排除在外,然后在进行素数筛选:
#求10万以内的素数 import datetime start = datetime.datetime.now() print(2) for i in range(3,100000,2): #从3开始,跳过偶数 for j in range(2,int(i**0.5+1)): if i%j == 0: break #else: #print(i) stop = datetime.datetime.now() print(stop-start)
运行结果: 0:00:00.406024 ,又快了不少。