判断一个数n是否为质数,最直观也是最先想到的方法是使用从2到n-1的数依次对它求模运算。
bool isPrime1(int x){
int i;
if(x<2)return 0;
for(i=2;i<x;i++){
if(x%i==0){
return 0;
}
}
return 1;
}
可以看出该算法复杂度为x,当反复运算时要消耗大量时间。
实际上判断质数只要算到x的平方根即可
以10000为例,平方根为100,算到100以后,如果该数是合数,可以写成a*b的形式,而a>100,那么b一定小于100,对小于100的数已经在之前的运算中验证过了,这样的运算当然没有意义。
bool isPrime2(int x){
int i,max;//用max保存sqrt(x)的值,不用在每次循环都计算sqrt(x)
if(x<2)return 0;
max = (int)sqrt(x);
for(i=2;i<max;i++){
if(x%i==0){
return 0;
}
}
return 1;
}
复杂度sqrt(x)
如果我们需要判断很多个数是否为质数,那可以先把质数表求出来保存,使用时查询即可,相当于计算一次,以后都不用在反复计算了。求质数表,先定义一个bool all[max],0和1值为false,其他为true然后从2开始,把4,6,8······等值改为false,反复执行到sqrt(x)。具体算法:
void findAllPrime(bool all[R],int x){
int i,j,max;
max = (int)sqrt(R);
for(i=2;i<max;i++)
all[i]=true;
all[0]=false;
all[1]=false;
for(i=2;i<R;i++){
if(all[i]){
for(j=2;i*j<R;j++)
all[i*j]=false;
}
}
// for(i=0;i<R;i++)
// if(all[i])
// printf("%d\n",i);
}//求出x以内所有数是否为质数,保存在数组all中,all长度至少为x
使用时all[i]即可返回是否为质数。
很明显该算法用空间换取时间。可以使用相当于一两次判断质数的时间来得到整个质数表,之后的计算几乎不需要时间,当x很大如1000000时,不使用这种方法肯定会时间超限。
参考资料