弟弟5•打印100-200的素数

本文详细介绍了素数的定义,以及三种常见的素数判断方法:试除法、假设法(通过标记法)和开平方法。提供了C语言的代码示例,并解释了每种方法的工作原理和优化思路。
摘要由CSDN通过智能技术生成

素数的定义

质数又称素数。 一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数。

方法一:试除法🐾

原理

用2到(本身-1)的数除以本身,但凡有一个能整除的,这个数都不是素数。【素数不能被除了1和它本身外的其他自然数整除。】

#include<stdio.h>
int main()
{
	int i = 100, j = 0; 
	for (i; i < 200; i++) 
	{
		for (j = 2; j < i; j++) 
		{
			if (i % j == 0) 
			{
				break;
			}
		}
		
		if (i == j) 
		{
			printf("%d ", i);
		}
	}
	return 0;
}

在这里插入图片描述

思路讲解

要使用两层for循环,外层用来实现100到200的遍历。内层用来判断每个数是不是素数。

j=2j<本身,即用2到(本身-1)的数依次除以本身。用if来判断每个数能否整除,如果能整除,就不用再判断了,使用break跳出内层for循环。

注意:一个break只能跳出一层循环。所以break后仍在外层循环中操作, i++,100到200的数继续遍历。

因为进入内层for循环的条件是j<i,所以当 j++到等于i时,无法再进入循环,但是 j 已经被++的这个事实无法撤回。

j 能够被++到与 i 相等,说明在此之前都没有出现“整除(i % j == 0)”的情况,因为整除会遇到break,这时 j 的++就会被打断,也就是 j 活不到相等那会就夭折了。因此(i == j)时的就是素数,打印即可。

方法二:假设法🐾

#include<stdio.h>
int main()
{
	int i = 100, j, count = 0; 
	for (i = 100; i <= 200; i++)
	{
		int flag = 1; 		
		for (j = 2; j < i; j++)
		{
			if (i % j == 0) 			
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1) 
		{
			count++; 
			printf("%d ", i); 
		}
	}
	printf("\n%d", count); 
}

在这里插入图片描述

原理

(你知道“攻1”和“受0”吗?无意冒犯)
假设全部都是素数并全部标记为1。
(将军,登记的时候都是“攻”。)

全部带去检验,如果发现不是素数 (娇),就把标记变为0。
(这个这么娇,是“受”吧)

只输出标记为1的。
(走,只有“攻”才能上战场!)

注意:因为标记flag不是绑在数上的,所以它是被每个数“暂时拥有”,辨明身份,立马使用,决定是否输出。所以它应该放在循环内。

思路讲解

遍历100到200的数。

建立标记变量flag=1。

试除法判断是否为素数。

如果不是素数,就把标记flag变为0,并break退出内层循环。在外层循环中继续向下执行if,因为flag=0,所以无法进入if

如果是素数,就不会被除了1和它本身外的其他自然数整除,即无法进入内层循环的if,即flag=1不会被改变。当结束内层循环继续向下执行时,这个数可以进入外层循环的if,被打印。

回到外层循环开头,i++,符合外层循环条件i<=200,进入循环,继续刚才的操作。

注意
那个count是用来计算素数的个数的,把它和“打印素数”放在一起。这里其他解法,如果要计数也是这么写。

因为都打印了,那肯定是确定为素数了,所以打印一个就计一个数。

要100到200遍历完了才可以输出 count 哦,要全部判断完了才知道count,所以count的打印放在循环外面。

方法三:开平方法🐾

#include<stdio.h>
#include<math.h> 
int main()
{
	int i = 100, j, count = 0;
	for (i; i <= 200; i++)
	{
		int flag = 1;
		for (j = 2; j <= sqrt(i); j++)  
		{
			if (i % j == 0)
			{
				flag = 0;
				break; 
			}
		}
		if (flag == 1)
		{
			count++;
			printf("%d ", i);
		}
	}
	printf("\n%d", count);
}

在这里插入图片描述

原理

数学事实:任意一个整数可以写成一个或多个乘积的形式。拆分成乘积的两个因子 a,b中必有一个因子小于或等于 a ∗ b \sqrt{a*b} ab ,如11=1*11,其中1就满足上述事实。

如果是素数,那么拆分出的两个因子中必然只有1满足上述数学事实,因为素数只能拆分为 (1*素数本身)。

所以如果在 2到 a ∗ b \sqrt{a*b} ab 之间找到了该数的乘积的因子,那么这个数就不是素数。

因为每个数需要比较的数字减少了,所以这种方法可以提高运行效率。

思路讲解

注意:使用开方函数sqrt()需要引头文件math.h

遍历100到200的数字。

结合了假设法的做标记的思路,其实唯一的区别就是,把用来判断的内层for循环的条件改了一下(把 j < i 变成了 j <= sqrt(i) 而已)。

还是像假设法一样,先全部标为flag=1,再逐个判断,如果不是素数,就把1改成0,最后只打印flag=1的。计数要和打印放一起,但是计数的最终结果打印,要在两层循环结束后,也就是放在循环外面。

悟了✨

判断输出类题目:遍历→逐个判断→(flag标记要被立即使用)(count计数要 放在循环外)→输出

❤️❤️❤️❤️❤️❤️ 恭喜! 恭喜! 又收了一名小弟! ❤️❤️❤️❤️❤️❤️

  • 29
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值