素数判别
由于1既不是素数也不是合数,所以下面暂未判断。如果需要则需特判如
if (num == 1) return false;
方法一
1 | bool isPrime_2( int num ) |
方法二(筛选法)
1 |
|
方法三(剪枝)
证明:令x≥1,将大于等于5的自然数表示如下:
······ 6x-1,6x,6x+1,6x+2,6x+3,6x+4 | 6x+5,6(x+1),6(x+1)+1 ······
可以看到,不在6的倍数两侧,即6x两侧的数为6x+2,6x+3,6x+4,由于2(3x+1),3(2x+1),2(3x+2),所以它们一定不是素数,再除去6x本身,显然,素数要出现只可能出现在6x的相邻两侧。这里有个题外话,关于孪生素数,有兴趣的道友可以再另行了解一下,由于与我们主题无关,暂且跳过。这里要注意的一点是,在6的倍数相邻两侧并不是一定就是质数。===>只需判断6两侧的是不是质数(6x-1、6x+1)
此时判断质数可以6个为单元快进,即将方法(2)循环中i++步长加大为6,加快判断速度,原因是,假如要判定的数为n,则n必定是6x-1或6x+1的形式,对于循环中6i-1,6i,6i+1,6i+2,6i+3,6i+4,其中如果n能被6i,6i+2,6i+4整除,则n至少得是一个偶数,但是6x-1或6x+1的形式明显是一个奇数,故不成立;另外,如果n能被6i+3整除,则n至少能被3整除,但是6x能被3整除,故6x-1或6x+1(即n)不可能被3整除,故不成立。===>综上,循环中只需要考虑6i-1和6i+1的情况(被本身更小的因数所除如22/11),即循环的步长可以定为6,每次判断循环变量k和k+2的情况即可,理论上讲整体速度应该会是方法(2)的3倍。代码如下:
1 | bool isPrime_3( int num ) |
for循环i从5开始而不是从7开始的原因:
从5、7开始的区别在于i <= sqrt(num)…如果是5的话,判断条件为25;如果是7的话,判断的条件就为49。
而仔细观察49内的所有质数,发现25之前的质数都是6k左右的数(6k-1,6k+1),而25以后,就不定都有了。如26则不为质数。 所以如果从5开始的话,那么25以内的数 都不会进入for循环,经过if(num %6!= 1&&num %6!= 5)
的筛选后,就都是素数了。 而如果是从7开始,那么25-49之内的数不符合条件却不会进入for循环,所以26缺少这个for的循环判断后就被误判为素数了。
==>以我浅薄的数学见识理解,25以内素数规律的巧合性使得 这些数不需要进入for循环判断,所以相比于从7开始的错误,5开始是正确的
给出Py代码
1 | import math |
参考:https://blog.csdn.net/huang_miao_xin/article/details/51331710
Author: Mrli
Link: https://nymrli.top/2018/10/15/素数判别/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.