素数的判断方法(从一般到高效)
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 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 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 9 if(!A[i]) 10 { 11 for(j=i+i;j 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 } 哈希打表输出2000000以内的所有素数: 1 //筛法求素数,哈希表查找 2 #include 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/》)