学习生物信息需要熟练掌握一门甚至多门编程语言,比如Python、R、C++,这取决于你的需求。
但语言只是工具,最关键的是如何合理使用工具去解决生物学问题,这需要你去多写、多查、多看来锻炼。不然给你把屠龙刀,你不去修炼,它也只是块废铁。工具有多好不仅取决于自身,更在于使用的人。
为了领略生物信息学的意义、美好、乐趣,之后我会分享更多文章,敬请期待~
本文内容主要包括:
- 质数和孪生质数的定义
- 质数分布的规律
- 两种实现方法,逐步优化~
为了更好的解决问题,我们先把“如何使用Python找质数”范围缩小一下,变成“如何使用Python找出100以内的素数”。
接下来,先明确概念,以便精确下手。
什么是质数?
质数( Prime number ):又称素数,指在大于1的自然数中,除了1和自身外,无法被其他自然数整除的数(也可定义为只有1和本身两个因素的数)。
与之相对的是合数,指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数。
试除法
根据质数的定义,可以有一个直观的思路:将
这种方法也叫试除法。
#!/usr/bin/env python
最终得到 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]。和搜索结果一致~
提一句,代码中 if __name__ == '__main__' 如何正确理解?
在Python中,一个.py文件就是一个模块。一般情况下,模块名就是文件名。
__name__ 存放当前模块名,当模块被直接运行时模块名为 __main__ 。
所以,if __name__ = ' __main__' 表示:当模块被直接运行时,该行以下的代码块将被运行;当模块是被导入(import)时,代码块不被运行。
试除法虽然简单,但是在测试大整数时很快会变得不切实际。因为可能的约数数量会随着n的增加而迅速增加。根据素数定理,小于
那么,有没有改进的方法呢?接着看下去吧~
质数分布规律
首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻,例如5和7,11和13,17和19。
用符号表示更容易理解:当n≥5时,如果n-1和n+1都为质数,那么n一定是6的倍数。
如何证明这个规律呢?
证明:设
则大于等于
即:
注意可以因式分解的式子。
其中,可以被整除,而,,分别可以写成,、的形式,所以它们都一定不是质数。
剩下的就是、、,代入几个数字试一下:
x = 1 时,为5,7,11
x = 2 时,为11,13,17
可以看到11被计算了两次。能不能减少计算,更好的表示大于等于5的质数呢?
实际上,可以用表示。为什么呢?因为。
所以大于等于5的质数可以表示为:,。这两个数都在身边不离不弃。
以上即证明了 质数分布的规律:大于等于的质数一定和的倍数相邻。
我们来试试用Python实现这种思路,建议新手先自行尝试再看下面代码,更容易理解:
#!/usr/bin/env python
结果是[2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97]。
相比之前试除法得出的[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97],多了几个合数,如25,55,49。
抓抓脑壳,究竟出了什么差错?
事实上,虽然质数是出现在
问题来啦~
- 为什么满足
或是()的数不一定是质数?
- 如何从满足
或是()的数中进一步筛出质数?
先着手第一个问题,我们“改造”一下这两个式子:
可以看到,如果
所以满足
所以如果想解决第二个问题,就得在代码中增加判断 n 是否为5或7的倍数。注意,这里n要大于7,不然会把5和7漏掉,它俩也是质数。
#!/usr/bin/env python
返回的结果是[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97],和试除法的结果一致。
同样的思路可以换一种方式写代码,另外也可以进一步使用time模块比较两种的时间:
#!/usr/bin/env python
到这里就大功告成啦~
为什么要比较代码运行时间?这一点可以查看如何理解算法时间复杂度的表示法,例如 O(n²)、O(n)、O(1)、O(nlogn) 等? 此知乎问题的回答都很优秀,值得了解!
想理解算法时间复杂度的表示法,先要搞明白何谓“算法时间复杂度”。
如果你学过开车的话(没有的话,回忆一下初中物理),就会知道,挂一档时,可能发动机转十几圈,车轮才转一圈;但挂5档时,可能发动机转一圈,车轮就转了一圈。
换句话说,在不同挡位,发动机转一圈,车轮转多少是不一样的。
这个玩意儿背后,其实就是初中学过的轮轴原理。
作者:invalid s
最后补充下“孪生质数猜想”:
孪生素数的问题已经有约200年的历史。
“ 孪生质数”是指两个相差为2的质数,所以上面我们说的和也互为孪生质数。
“ 孪生素数猜想”是说,存在无穷对孪生质数。在1900年的国际数学家大会上,希尔伯特将孪生质数猜想列入了他那著名的23个数学问题。
关于质数还有很多有趣的东西,比如梅森素数、数论。你可以自行了解,这里就不展开了。
现在,你学会了如何用Python找质数了吗?
参考:
- 质数-维基百科
- Python质数判断——菜鸟教程
- 判断一个数是否为质数的三种方法
- 如何用Python判断一个数是否是质数?
- 孪生素数猜想,张益唐究竟做了一个什么研究?