判断素数的多种方法(PTAL1-028 判断素数解题有感)

今天在写PTA团体程序设计天梯赛-练习集时,被一道简单的判断素数的题给卡住了,试了几种方法都是会有一些测试点超时,遂上网查阅了相关的判断素数的方式,经过多个不同的方法解决题目之后,发现竟然有这么多不同层次的判断素数的方法,遂想记录下自己这么久以来学过的这些判断方法,以供大家参考!

一、最最简单暴力的解法

我们先来看看质数的定义:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。所以素数最重要的一点是它只能被1或者它本身整除,所以这里我们可以让
这个整数n被2,3,4…n-1全部除一次,如果中间出现了能被整除的情况,则不是素数。

#include<stdio.h>
int main()
{
	int i;//这里以判断1到1000以内的素数为例
	int j;
	for (i = 1; i <= 1000; i++)
	{
		int k=1;
		for (j = 2; j < i; j++)
		{
			if (i % j == 0)
				k = 0;
		}
		if (k == 1) printf("%5d ",i);
	}
	return 0;
}

这是最最基础,最最简单粗暴的方法,得到的结果如下
在这里插入图片描述
接下来我们在此基础上做出一些优化

二、一些简单的优化

1.减少遍历的时间

我们先举一个例子,10可以被2合5整除,那么当程序遍历到2和5时的效果是相同的,都可以判断10不是素数,所以我们只要发现能被整除的情况便可退出程序不再遍历,除此之外,如果遇到了素数n,我们也不需要遍历到n-1,只要遍历到n的平方根即可,因为如果在2到根号n之间找不到能整除i的数字,那么在根号n到n-1之间也不会出现能整除i的数字,所以我们可以对程序做出如下优化

#include<stdio.h>
#include<math.h>
int main()
{
	int i;//这里以判断1到1000以内的素数为例
	int j;
	for (i = 1; i <=1000 ; i++)
	{
		int k = 1;
		if (i == 1)
			k = 0;
		else
		{
			/*for (j = 2; j*j <= i; j++)//这里是用j*j来保证j不超过根号i
			{
				if (i % j == 0)
					k = 0;
					break;
			}*/
			for (j = 2; j <= sqrt(i); j++)//这里使用库函数来计算出根号i
			{
				if (i % j == 0)
				{
					k = 0;
					break;//这里是出现整除的情况便不再遍历,退出循环
				}
			}
			if (k == 1) printf("%5d",i);
		}
	}
	return 0;
}
这里我们将使用j*j<=i的这一种方法进行了注释,因为这种方法相对使用库函数来说,每次判断
时都要计算一次,增加了程序运行的时间,所以我们这里只是列出而不推荐使用。

2.使用奇数

我们不难发现这样的规律,除了2以外的偶数一定都不是素数,因为他们至少都可以被2给整除,所以我们可以在遍历之前判断这个数是否是奇数,如果是奇数则遍历,是2以外偶数则直接判断为不是素数,同时我们再遍历的时候也可以进一步简化,因为已经排除了所有的除2以外的偶数,所以我们在遍历的时候也可以跳过偶数了,从3开始,每次递增2,这又可以为计算机节省出一些计算的时间,代码如下

#include<stdio.h>
#include<math.h>
int main()
{
	int i;//这里以判断1到1000以内的素数为例
	int j;
	for (i = 1; i <=1000 ; i++)
	{
		int k = 1;
		if (i == 1||(i%2==0&&i!=2))
			k = 0;
		else
		{
			for (j = 3; j <= sqrt(i); j+=2)
			{
				if (i % j == 0)
				{
					k = 0;
					break;
				}
			}
			if (k == 1) printf("%5d",i);
		}
	}
	return 0;
}

3.再简化版

今天我在网络上浏览的时候,发现了一个有意思的性质,那就是大于等于5的素数,一定是与6及其倍数相邻,所以这里我们又可以对这段代码再进行简化,排除更多的数据

#include<stdio.h>
#include<math.h>
int is_Prime(int k)
{
	if (k == 1 || (k >= 5 && (k % 6 != 1 && k % 6 != 5)) || (k % 2 == 0 && k != 2))
		return 0;
	else
		return 1;
}

int main()
{
	int i;
	int j;
	for (i = 1; i <= 1000; i++)
	{
		int ret = is_Prime(i);
		if(ret)
		{
			int k = 1;
			for (j = 3; j <= sqrt(i); j+=2)
			{
				if (i % j == 0)
				{
					k = 0;
					break;
				}
			}
			if (k == 1)printf("%5d",i);
		}
	}
	return 0;
}

以上便是用简单遍历方法对素数进行判断了,下面我们介绍最后一种,运用数组来判断素数的放大

三、运用数组来判断素数的方法

这里用到我们发现的素数的另一种性质:如果质数n不能被小于n的质数整除,则n就是质数,所以我们这里用数组来存储素数,然后在检验素数的时候,只要拿数组中的素数相除来判断即可,这个代码相对复杂一些,但是非常好用,且需要一定的基础

#include<stdio.h>
int main()
{
	int prime[1000]={0};//存储素数的数组
	int i,j;
	int count = 1;//数组的下标
	prime[0] = 2;//先放入第一个素数
	for (i = 3; i <= 1000; i++)
	{
		int k = 1;
		for (j = 0; j < count; j++)
		{
			if (i % prime[j] == 0)
			{
				k = 0;
				break;
			}
		}
		if (k == 1)
		{
			prime[count] = i;
			count++;
		}
	}
	for (i = 0; i < count; i++)
		printf("%5d", prime[i]);
	return 0;
}

以上便是个人所知的所有的判断素数的方式了,后续应该还会对其有所增加,如果您有什么好的建议或者好的方法,也欢迎您提出来。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值