【C语言】判断一个数是否是素数(质数) 常规思路---详细讲解 (需回看)

素数(质数)的定义

大于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就是素数了。

猜你喜欢

转载自blog.csdn.net/qq_44731019/article/details/123609785