素数的唯一性定理与求1到100之间所有素数的问题
求1到100之间的所有素数的问题。
如果一个数是素数,姑且叫这个数为P好了,那么P是不可能被1到P之间除1和P外的任何一个其他的素数整除。那么有如下算法:
算法1
int GetPrimeFromOne2Hundred()
{
int p[30]={0};
int i,j;
int count1=0,count2=0;//用于累计循环次数
for(i=1;i<=100;i++)
{
j=0;
while(p[j]!=0&&(p[j]==1||i%p[j]!=0))
{
j++;
count1++;
}
if(p[j]==0)
{
p[j]=i;
count2++;
}
}
for(i=0;i<30;i++)
printf("%d\t",p[i]);
printf("%d\t%d\t%d\t",count1,count2,count1+count2);//输出循环次数
return 0;
}
count1的值为436,count2的值为26,总共为462次。
其实对于一个整数N,将其分解成两个因数,任一一个因数的减小都会造成另外一个因数的增大。假设N=i*j,i和j都是整数,那么N%i与N%j都是等于0,在这个问题中二者的意义是一样的。于是我们可以找到一个数m,即只要N不能被小于m的整数整除的话,那么就可以断定N是素数,这个数既是m=(int)sqrt(N),根据“素数的唯一性定理”,范围还可以缩小,只要N不能被小于m的素数整除的话,那么就可以断定N是素数。于是该算法可改进如下:
算法2
int GetPrimeFromOne2Hundred()
{
int p[30]={0};
int i,j,k,n;
int count1=0,count2=0;//用于累计循环次数
n=0;
for(i=1;i<=100;i++)
{
j=0;
k=(int)sqrt((double)i);
while(p[j]!=0&&p[j]<=k&&(p[j]==1||i%p[j]!=0))
{
j++;
count1++;
}
if(p[j]==0||p[j]>k)
{
p[n]=i;
n++;
count2++;
}
}
for(i=0;i<30;i++)
printf("%d\t",p[i]);
printf("%d\t%d\t%d\t",count1,count2,count1+count2);//输出循环次数
return 0;
}
count1的值为206,count2的值为26,总共为232次。
循环总次数,与算法1相比,算法2减少230次。但随着范围的扩大,例如求1到1000之间的素数,则对于算法1,循环总次数为15788+169=15957次;而对于算法2,循环总次数为2969+169=3138次。可见算法2相对算法1,效率有很大提高。