判断素数———两种高效算法


相信大家在学习的过程中,时不时就会遇到判断素数的问题。今天就让我们来讨论讨论这个有趣的数学问题,看看如何更高效的来解决它吧!

在刚开始接触到这个问题时,我只想到了利用一个循环去在目标数的全部范围内一个一个进行判断的方法。在了解了一些有关素数的知识后,就只用查找到目标数的平方根了。不过查找的效率还是有些低,接下来的两个方法可以更加高效的解决这个问题。

一.加长步数
素数就是只能被1和其自身整除的整数。现把判断素数的问题分成两个部分:5之前,5和5之后。
对于5之前,一共只有2和3两个素数。
对于5和5之后,让我们来分析一下其规律。
对于5和5之后的数可以分解成如下形式:
6n - 1, 6n,6n + 1,6n + 2,6n + 3,6n + 4,6n + 5,6(n + 1)
6n,6n + 2,6n + 3,6n + 4都有对应的数可以将其整除。所以素数就只可能出现在6n的前后。只需要判断这些数便可以确定目标数是否是素数了。

代码实现:

bool isprime(int n)
{
	if (n <= 3)
		return n > 1;
		
	//如果目标数不在6的前后则一定不是素数
	if (n % 6 != 1 && n % 6 != 5)
		return false;

	//增长每次判断的步数,增加效率,判断到目标数的平方根
	for (int i = 5; i <= sqrt(n); i += 6)
		if (n % i == 0 || n % (i + 2) == 0)//如果目标数可以被6前后的数整除,便不是素数
			return false;
	return true;
}

二.素数筛(简化版)
现在让我们来换一个思路考虑这个问题。刚刚是先得到一个目标数,然后再对其进行判断。我们也可以在得到目标数之前就将一段范围内的每一个数是否是素数判断出来,并用数组将结果记录下来。在得到目标数之后,只需要直在数组中进行查找即可。
利用布尔数组记录判断结果。不过在使用其记录结果之前,我们可以先将其中的每个奇数项的结果设置为真,每个偶数项都结果都记录为假。接下来便是判断每一个奇数是否是素数了。如果某个奇数为素数,则将其的倍数的判断结果都设置为假。在完成全部的判断后,我们就到查找的依据啦。

代码实现:

#include <iostream>
#include <cmath>
using namespace std;

const int N = 10000;
bool prime[N + 1] = {false, false, true};
//注意这里数组长度的声明,如果为N则会有一个数的真假无法保存导,致程序运行崩溃。

bool isprime(int);//使用加长步数的方法进行判断

int main()
{
    int i, j;

    for (i = 3; i <= N; i++)//数组初始化(严格上说不叫初始化,感觉这样说比较舒服~)
        if (i % 2 == 0) 
            prime[i] = false;
        else 
            prime[i] = true;

    for (i = 3; i <= sqrt(N); i = i + 2)
        if (prime[i])
            for (j = i + i; j < N; j += i)//将为素数的奇数的倍数的结果都设置为假(定语有些多= =)
                prime[j] = false;

    for (i = 3; i < N; i++)
        if (prime[i])
            cout << i << ' ';

    return 0;
}

bool isprime(int n)
{
    if (n <= 3)
        return n > 1;

    if (n % 6 != 1 && n % 6 != 5)
        return false;

    for (int i = 5; i <= sqrt(n); i += 6)
        if (n % i == 0 || n % (i + 2) == 0)
            return false;
    return true;
}

好啦,关于素数判断问题的讨论就先到这里啦!上面的方法在判断大量数据是否是素数的时,可以节省大量时间。有兴趣的小伙伴可以去尝试尝试哦~

发布了4 篇原创文章 · 获赞 4 · 访问量 163

猜你喜欢

转载自blog.csdn.net/weixin_45816550/article/details/104648487
今日推荐