素数,又称质数。其特征为除开1和其本身外,没有能将其整除的数。
举个例子,2、3、5均为素数,而4则不为素数(因为2可以将其整除),并且1也不为素数。
那么根据定义可轻松得到代码如下
#include<stdio.h>
int main ()
{
int num,flag=1; //flag用以标记状态,为1则认为其为素数,否则则不为素数(默认其为素数)
scanf("%d",&num); //num即想要判定的数
for(int i=2;i<num;i++) //自2开始到num-1
{
if(num%i==0) //一旦出现求余结果等于0的情况(即i可以整除num)说明num非素数
{
flag=0; //将flag修改为0,即代表该数不为素数
break; //既然已经判定为非素数了,后续的循环再无必要,直接退出节省时间。
}
}
if(flag&&num!=1) //注意此处num!=1,因为1也不视为素数,但是如果i为1的话flag是不会被修改为0的(for循环的内容根本不会执行)
//所以需要我们手动额外增加判定条件
{
printf("%d是素数",num);
}
else
{
printf("%d不是素数",num);
}
system("pause");
return 0;
}
但这个根据定义直接写出的代码非常简单粗暴,但也有弊端,当num(也就是所需要判定的数)过大时,需要消耗很多的时间,循环次数即num-2,即时间复杂度为O(n),当num较大时非常容易超时,所以调用math库下的sqrt函数,可以将时间复杂度压缩为O()。
#include<stdio.h>
#include<math.h>
int main ()
{
int num,flag=1; //flag用以标记状态,为1则认为其为素数,否则则不为素数(默认其为素数)
scanf("%d",&num); //num即想要判定的数
for(int i=2;i<=sqrt(num);i++) //自2开始到根号下num
{
if(num%i==0) //一旦出现求余结果等于0的情况(即i可以整除num)说明num非素数
{
flag=0; //将flag修改为0,即代表该数不为素数
break; //既然已经判定为非素数了,后续的循环再无必要,直接退出节省时间。
}
}
if(flag&&num!=1) //注意此处num!=1,因为1也不视为素数,但是如果i为1的话flag是不会被修改为0的(for循环的内容根本不会执行)
//所以需要我们手动额外增加判定条件
{
printf("%d是素数",num);
}
else
{
printf("%d不是素数",num);
}
system("pause");
return 0;
}
而除此之外,也可以使用一个记忆数组,记录所有小于num的素数,只需要遍历这个记忆数组,只要没有出现能将num整除的素数,则可认为该num也是素数,即欧氏筛(由埃氏筛改进而来,此处不多赘述),因为实际上多数情况下非素数的个数远远大于素数的个数,以这个方法能大大减少循环的次数,并且在需要判定多个数是否为素数时可以重复利用,大大节省了时间。代码如下
#include<stdio.h>
int main ()
{
int a,i,m,flag,len=1; //len即记忆数组arr的长度
int arr[1000]={2}; //数组长度由实际情况决定,此处粗略设为1000,同时将首个数据初始化为2(第一个素数为2)
scanf("%d",&a); //读入所需要判定的数
for(m=3;m<=a;m++) //已将2列入记忆数组,故而此处m从3开始
{
flag=1;
for(i=0;i<len;i++) //循环判素,但注意此处的循环是对记忆数组arr循环
{
if(m%arr[i]==0)
flag=0;
}
if(flag)
{
arr[len++]=m; //如果当前数为素数,则列入记忆数组,并且记忆数组的长度len加一
}
}
for(i=0;i<len;i++) //循环输出记忆数组中已记录的素数
{
printf("%d是素数\n",arr[i]);
}
if(arr[len-1]==a) //显然如果输入的数为素数,那么记忆数组中所记录的最后一位就应该等于这个数
{
printf("%d是素数\n",a);
}
else
{
printf("%d不是素数\n",a);
}
return 0;
}