【C语言】素数的N种代码形式

 The words written in front

大家好,我是xiaoxie,希望你看完之后对你能有所帮助,不足之处,请批评指正!

希望可以和大家一起交流学习进步!

【C语言】素数的N种代码形式_第1张图片

Introduction

大家都知道:“质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数,那如果我们想知道1--200之间的素数是什么,那该如何用C语言去解决这个问题呢。

算法介绍------试除法

试除法是一种简单而直观的质数判定方法。其基本思想是:对于正整数n,若n能被2到n-1之间的任一整数整除,则n非质数;否则,n为质数。

以下是基于试除法算法的C语言实现:

​
#include
#include
int main()
{
	int n = 0;
	int count1 = 0;//计算素数个数
	for (n = 100; n <= 200; n++)
	{
		
		int j = 0;
		for (j = 2; j 

【C语言】素数的N种代码形式_第2张图片

要想知道上面的时间复杂度,我们可以看它到底for循环了几次。我们可以对上述的代码增加一个对循环次数的监视,这样就可以直观的了解这段代码高不高效

代码实现如下:

#include
#include
int main()
{
	int n = 0;
	int count1 = 0;//计算素数个数
	int count2 = 0;//计算循环次数
	for (n = 100; n <= 200; n++)
	{
		
		int j = 0;
		for (j = 2; j 

【C语言】素数的N种代码形式_第3张图片

由此我们可以得出这段代码仅仅只是100个数就循环了3292次,而我们判断一个算法是否优劣是看它是否高效,执行效率是否高效。所以我们应该对它做出优化。

试除法优化版--开平方

n=a*b,例如16=2*8=4*4,意味着a和b中至少有一个数字<=开平方n,如果在开平方之前仍未找到能整除i的数,就不可能再找到其他的数整除i,则该数为素数.以下是代码实现:

#include
#include
int main()
{
	int n = 0;
	int count1 = 0;//计算素数个数
	int count2 = 0;//计算循环次数
	for (n = 100; n <= 200; n++)
	{
		int j = 0;
		for (j = 2; j <= sqrt(n); j++)//使用sqrt库函数要引用#include
		{
			count2++;
			if (n % j == 0)//说明有除n和n本身的其他数整除,说明i不是素数
				break;
		}
			if (j>sqrt(n))//说明2到根号n中没有n的因子
			{
				printf("%d\n", n);
				count1++;
			}
			

	}printf("\ncount1=%d", count1);
	printf("\ncount2=%d", count2);
	return 0;

}

【C语言】素数的N种代码形式_第4张图片

由上述代码我们大大的优化算法的执行效率,减少了程序实现功能的时间。

试除法优化版--去偶数

由素数定义我们可知素数只能被1和它本身整除那么只要n为偶数就一定不是素数,由此我们就可以从源头排除一些数。以下是代码实现:

#include
#include
int main()
{
	int n = 0;
	int count1 = 0;//计算素数个数
	int count2 = 0;//计算循环次数
	for (n = 100; n <= 200; n++)
	{
		if (n % 2 == 0)//判断n是否为偶数
		{
			
			continue;
		}
		int j = 0;
		for (j = 2; j <= sqrt(n); j++)//使用sqrt库函数要引用#include
		{
			count2++;
			if (n % j == 0)//说明有除n和n本身的其他数整除,说明i不是素数
				break;
		}
			if (j>sqrt(n))//说明2到根号n中没有n的因子
			{
				printf("%d\n", n);
				count1++;
			}
			

	}printf("\ncount1=%d", count1);
	printf("\ncount2=%d", count2);
	return 0;

}

【C语言】素数的N种代码形式_第5张图片由此可见count2=342,只循环了342,又减少了程序实现功能的时间,提高了效率。所以博主强烈的建议大家掌握这个方法。这样你和其他的人做一道题时,直接就和其他人拉开了差距。那么判断素数就一种算法了嘛,接下来博主再为大家介绍一种算法

埃拉托色尼筛选法

有些时候,除了检验给定整数x是否为质数的函数之外,如果能事先准备出质数数列或质数表,就可以帮助我们更有效地求解质数的相关问题。
埃拉托色尼筛选法(The Sieve of Eratosthenes)可以快速列举出给定范围内的所有质数,这个算法如下步骤生成质数表。
埃拉托色尼筛选法

  1. 列举大于等于2的整数。
  2. 留下最小的整数2,删除所有2的倍数。
  3. 在剩下的整数中留下最小的3,删除所有3的倍数。
  4. 在剩下的整数中留下最小的5,删除所有5的倍数。
  5. 以下同理,留下仍未被删除的最小整数,删除该整数的倍数,一直循环到结束。

以最小的4个质数为例,其求解过程如图。
原始表:

【C语言】素数的N种代码形式_第6张图片第一轮:【C语言】素数的N种代码形式_第7张图片第二轮:

【C语言】素数的N种代码形式_第8张图片第三轮:

【C语言】素数的N种代码形式_第9张图片第四轮:【C语言】素数的N种代码形式_第10张图片根据上表提供的思路,我们可以用C语言实现这个算法的应用

代码如下:

​
#include 
#include 

#define MAX 200

// 判断一个数是否为素数
bool is_prime(int num) {
    if (num < 2) { // 如果一个数小于2,那么它不是素数
        return false;
    }
    for (int i = 2; i * i <= num; i++) { // 遍历2到num的平方根
        if (num % i == 0) { 
            // 如果num能被i整除,那么它不是素数
            return false;
        }
    }
    return true; // 如果num不能被2到它的平方根之间的任何数整除,那么它是素数
}

// 使用埃拉托色尼筛选法找出1到MAX之间的所有素数
void sieve_of_eratosthenes() {
    bool is_prime[MAX + 1]; // 创建一个布尔类型的数组,用于存储1到MAX之间的所有数是否为素数
    for (int i = 2; i <= MAX; i++) { // 将所有数初始化为素数
        is_prime[i] = true;
    }
    int count = 0; // 记录循环次数
    for (int i = 2; i * i <= MAX; i++) { // 遍历2到MAX的平方根
        if (is_prime[i]) { // 如果i是素数
            for (int j = i * i; j <= MAX; j += i) { // 将i的所有倍数标记为非素数
                is_prime[j] = false;
            }
            count++; // 执行了一个完整的循环
        }
    }
    printf("循环次数: %d\n", count); // 打印循环次数
    for (int i = 2; i <= MAX; i++) { // 打印所有素数
        if (is_prime[i]) {
            printf("%d ", i);
        }
    }
}

// 主函数
int main() {
    sieve_of_eratosthenes();
    return 0;
}

​

埃拉托色尼筛选法需要占用一部分内存空间(与待检验整数的最大值N成正比),但其复杂度只有O(N log log N)。

总结

素数还有很多种算法可以求解,有句老话叫做”活到老学到老“,C语言更是一门需要不断学习,不断设计出更优解的语言,希望这篇文章可以帮助你对C语言的学习提供一点帮助,不足之处,请多多谅解,让我们一起共同学习共同成长。【C语言】素数的N种代码形式_第11张图片

你可能感兴趣的:(算法,c语言,算法,开发语言)