素数(质数)的定义
大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做
质数(也叫素数)
;否则称为合数。 0和1既不是质数也不是合数,最小的质数是2。
判断素数方法(一)常用但效率不是很高
这种方法比较好理解,也容易想到。
但是 这种方法效率不是很高。
//判断质数(素数)方法一
#include <stdio.h>
int main()
{
int n,i;
printf("请输入大于等于2的整数:");
scanf("%d",&n);
putchar('\n');
if(n<2)
{
printf("%d不是质数(素数)!\n");
}
else{
for(i=2;i<n;i++)
{
if(n%i==0) //如果有大于2的可以除尽的数,则不是素数
break;
}//注意这里的i是否被除尽,若除尽了,则通过break跳出for循环后直接通过下面的if判断(i<n)输出n不是素数
//若除不尽,那么for循环中的break则执行不到,亦即整个for循环都执行了,直到i++ = n不符合循环条件时才跳出循环,执行下面的else 即打印n是素数
printf("(i这时是:%d)\n\n",i); //测试 意为看看第一个不符合的(可以除尽的)数是多少?
if(i<n) //即 存在2~(n-1)之间有因数
{
printf("%d不是素数(质数)!\n",n);
}
else
printf("%d是素数(质数)!\n",n);
}
return 0;
}
测试:
同样,也可以将上述 处理是不是素数 的过程封装成一个函数,意思是一样的。
//将上述方法封装为函数Prime
#include <stdio.h>
int Prime(int n); //函数原型声明
int main()
{
int n;
printf("请输入大于等于2的整数:");
scanf("%d",&n);
putchar('\n');
Prime(n); //调用函数Prime来处理该数是不是素数
return 0;
}
int Prime(int n) //函数定义
{
int i;
if(n<2)
{
printf("%d不是质数(素数)!\n");
}
else{
for(i=2;i<n;i++)
{
if(n%i==0) //如果有大于2的可以除尽的数,则不是素数
break;
}
printf("(i这时是:%d)\n\n",i); //测试 意为看看第一个不符合的(可以除尽的)数是多少?
if(i<n) //即 存在2~(n-1)之间有因数
{
printf("%d不是素数(质数)!\n",n);
}
else
printf("%d是素数(质数)!\n",n);
}
}
那么再测试一下:
判断素数方法(二)借用数学函数 效率较高
这里所说的“借用数学函数”,也只是用来求了一次平方根,核心思想并不是利用数学函数求素数。
其实还是通过取余来判断,只不过这里所需判断的数量并不需要那么多了。
//判断素数方法二:求数n的 算术平方根p,并对<=p的所有数 取余看是否为0。
//若有为0的(即有除尽的),则数n不是素数,否则n是素数
#include <stdio.h>
#include <math.h>
int main()
{
int n,i,k;
printf("请输入大于等于2的整数:");
scanf("%d",&n);
putchar('\n');
k=sqrt(n); //即对n开平方
printf("对%d开平方后得到的k是:%d\n",n,k); //测试,看对n开方得到的k是多少
putchar('\n');
for(i=2;i<=k;i++){
if(n%i==0)
break;
}
printf("(此时,i是%d)\n",i);//测试,亦为看看此时 第一个满足取余等于0 的因子是多少
putchar('\n');
if(n<2) //当输入的n小于2时,直接 输出 n不是 素数
{
printf("%d不是素数!\n",n);
}
else if(i<=k){
printf("%d不是素数!\n",n);
}
else{
printf("%d是素数!\n",n);
}
return 0;
}
测试如下:
可以看到,对99开方之后得到的数k是9,这是因为k定义的是整型数字。
我选取了几个和方法一中的测试相同的数字,测试结果是一样的。因此这种方法也是正确的。至于选用哪种方法,就看读者心里是怎么想的了。
那么为什么取余时,法二不用判断那么多次呢?或者说,为什么选取的i 小于等于k 这个范围就可以判断出数n是不是素数呢?可以这么想:当判断数n不是素数
时,如果有小于或者等于 k 的数 i,都能把n整除,那么n就肯定不是素数了。(因为素数的因子只有1和它本身哪!)
至于判断n是素数,这样想,素数的对立面是合数
,比如4是合数(除了1和它本身之外,还有别的因子,那么这个数就叫做合数)。
对于数n,如果它能分解成 n=a*b , 那么a和b中必然有一个大于等于根号n,另外一个小于等于根号n,也就是说一个合数n必然有一个因子是小于等于根号n的。所以对一个数n,只要检验它有没有小于等于根号n的因子就可以了(检验小于等于n的因子使得循环次数变少,这也是简化的原因)
例如,36是合数。36开平方是6,此外,36还有好几个因子,例如1,2,3,4,6,9,36。其中,1、2、3、4都是小于6的。
36 = 4 * 9 = 6 * 6。其中,4<6,而9>6。这就是为什么说“ 对于数n,如果它能分解成 n=a*b , 那么a和b中必然有一个大于等于根号n,另外一个小于等于根号n,也就是说一个合数n必然有一个因子是小于等于根号n的”。
所以说,这就是为什么判断一个数是不是素数时,为什么可以使用方法二了,即只需要判断有没有小于或等于其开平方的因子存在,所有,则数n就不是素数了。反之,数n就是素数了。