素数的判断方法(从一般到高效)

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 }

哈希打表输出2000000以内的所有素数:

 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/》)

posted @ 2018-07-10 08:54  无心小男  阅读(14205)  评论(3编辑  收藏  举报