素数的判断方法(从一般到高效)
http://dongxicheng.org/structure/prime/
1. 素数判定问题
素数判定问题是一个非常常见的问题,本文介绍了常用的几种判定方法。
2. 直观判断
素数的定义是,除了能被1和它本身整除而不能被其他任何数整除的数。根据素数定义 只需要用2到n-1去除n,如果都除不尽,则n是素数,否则,只要其中有一个数能整除则n不是素数。
1 bool prime_1(int n){ 2 for(int i=2;i<n;i++){ 3 if(n%i==0) 4 return flase;//不是素数 5 } 6 else 7 return true;//是素数 8 }
3. 直观判断改进
上述判断方法,明显存在效率极低的问题。对于每个数n,其实并不需要从2判断到n-1,我们知道,一个数若可以进行因数分解,那么分解时得到的两个数一定是一个小于等于sqrt(n),一个大于等于sqrt(n),据此,上述代码中并不需要遍历到n-1,遍历到sqrt(n)即可,因为若sqrt(n)左侧找不到约数,那么右侧也一定找不到约数。C++代码如下:
1 bool prime_2(int n){ 2 for(int i=2;i<=sqrt(n);i++) 3 if(n%i==0) 4 return flase;//不是素数 5 else 6 return true;//是素数 7 }
3. 筛法求素数
更高效地素数判断方法应该是将素数预先保存到一个素数表中,当判断一个数是否为素数时,直接查表即可。这种方法需要解决两个问题:
(1) 怎样快速得到素数表?(采用筛选方法)
(2) 怎样减少素数表的大小?(采用位图数据结构)
对于1到n全部整数,逐个判断它们是否是素数,找出一个非素数,就把它挖掉,最后剩下的就是素数。具体方法是:
<1> 定义is_primer[i] = true;
<2> 从2开始,依次遍历整个primer(直到sqrt(N)),如果primer[i]=true,则primer[n*i]=false
如1,2,3,4,5,6,7,8,9,10,则
从2开始遍历:
primer[2]=true,则primer[4]= primer[6]= primer[8]= primer[10]= false,2的倍数
primer[3]=true,则primer[6]= primer[9]= false,3的倍数
1 #include<stdio.h> 2 #define M 2000000 3 char A[2000000]={"\0"}; 4 int S[150001]={0}; 5 int main() 6 { 7 int m,n,i,j,k=0; 8 for(i=2;i<M;i++) 9 if(!A[i]) 10 { 11 for(j=i+i;j<M;j+=i) 12 A[j]=1; 13 S[++k]=i; 14 } 15 for(i=0;i<150001;i++) 16 printf("%d\t",S[i]); 17 return 0; 18 }
1 //筛法求素数,哈希表查找 2 #include<stdio.h> 3 #define MAX 2000000 4 int prime[2000000]; 5 int main(){ 6 for(int i=2;i<=MAX;i++) 7 prime[i]=1; 8 prime[1]=0; 9 for(int i=2;i<=MAX;i++)//打表 10 for(int j=2*i;j<=MAX;j+=i) 11 prime[j]=0;//偶数标记0 15 for(int i=2;i<=2000000;i++) 16 if(prime[i]==1) 17 printf("%d\t",i);//输出素数 18 return 0; 19 }
至今为止,没有任何人发现素数的分布规律,也没有人能用一个公式计算出所有的素数。关于素数的很多的有趣的性质或者科学家的努力,如:
(1) 高斯猜测,n以内的素数个数大约与n/ln(n)相当,或者说,当n很大时,两者数量级相同。这就是著名的素数定理。
(2) 十七世纪费马猜测,2的2^n次方+1,n=0,1,2…时是素数,这样的数叫费马素数,可惜当n=5时,2^32+1就不是素数,至今也没有找到第六个费马素数。
(3) 18世纪发现的最大素数是2^31-1,19世纪发现的最大素数是2^127-1,20世纪末人类已知的最大素数是2^859433-1,用十进制表示,这是一个258715位的数字。
(4) 孪生素数猜想:差为2的素数有无穷多对。目前知道的最大的孪生素数是1159142985×2^2304-1和1159142985×2^2304+1。
(5) 歌德巴赫猜想:大于2的所有偶数均是两个素数的和,大于5的所有奇数均是三个素数之和。其中第二个猜想是第一个的自然推论,因此歌德巴赫猜想又被称为1+1问题。我国数学家陈景润证明了1+2,即所有大于2的偶数都是一个素数和只有两个素数因数的合数的和。国际上称为陈氏定理。(摘自《http://chuanbindeng.blog.163.com/blog/static/67886226200982892139468/》)