【解题+详细分析】判定是否为素数(质数)

题目如下

例 5.9】 输入一个大于3的整数n,判定他是否为素数(质数也称素数)

我写的

int main()
{
	int i = 0;
	int n = 0;

	scanf("%d", &n);
	for (i = 1; i < n; i++)
	{
		if (n % 2 == 0 || n % (n - 1) == 0)  // 逻辑错误
		{
			break;
		}
		//printf("%d ", n / i);
	}
	if (n % 2 == 0 || n % (n - 1) == 0) // 逻辑错误
	{
		printf("不是质数");
	}
	else
	{
		printf("是质数");

	}
	return 0;
}

针对我的解法进行分析

这段 C 语言代码的主要目的是判断输入的整数 n 是否为质数。

以下是对代码的详细分析:

  • main 函数开始,定义了两个整型变量 in ,并初始化为 0
  • 然后,使用 scanf 函数获取用户输入的整数,并将其存储到 n 中。
  • 接下来是一个 for 循环,从 i = 1 开始,只要 i < n 就会执行循环体。
    • 在循环体中,通过判断 n % 2 == 0 || n % (n - 1) == 0 来决定是否提前结束循环。如果 n 能被 2 整除或者能被 n - 1 整除,就执行 break 语句跳出循环。
  • 循环结束后,再次判断 n % 2 == 0 || n % (n - 1) == 0
    • 如果条件成立,输出 不是质数
    • 否则,输出 是质数

我的写法存在的逻辑错误

  • 检查是否为质数的条件不正确。一个数 n 是质数,当且仅当它不能被大于 1 且小于 n 的任何整数整除。在这段代码中,只检查了能否被 2n - 1 整除,遗漏了其他可能的因子。

正确解法

#include <stdio.h>

int main() {
    int n, i, isPrime = 1;
    scanf("%d", &n);
    if (n <= 3) {
        printf("输入的数应大于 3\n");
        return 0;
    }
    for (i = 2; i * i < n; i++) {
        if (n % i == 0) {
            isPrime = 0;
            break;
        }
    }
    printf("%s\n", isPrime? "是质数" : "不是质数");
    return 0;
}

正解分析

  1. for (i = 2; i * i < n; i++)i 的初始值为 2 ,这是因为 1 肯定能整除任何数,所以从 2 开始检查。

  2. 判断条件 i * i < n

    假设一个数 n 可以分解为两个因数 ab ,且 a <= b ,那么 a * a <= n 。所以我们只需要检查到 i * i < n 就可以了,超过这个范围,如果还没有找到能整除 n 的数,那么 n 就是质数。这样可以减少不必要的循环次数,提高效率。

  3. isPrime 是一个标志变量,初始值为 1 ,表示我们先假设输入的数 n 是质数。当在循环中找到一个能整除 n 的数(即 n % i == 0 )时,就将 isPrime 设为 0 ,表示 n 不是质数。最后根据 isPrime 的值来输出 n 是否为质数。

    直接使用 break 只是提前结束了循环,但并不能明确地标识最终的判断结果。

    使用 isPrime 变量可以更清晰、明确地记录最终的判断结论。当在循环中找到了能整除 n 的数,将 isPrime 置为 0 。循环结束后,通过检查 isPrime 的值来确定 n 是否为质数。

    这样做的好处是:即使循环因为其他原因(比如达到了循环条件)正常结束,我们仍然可以通过 isPrime 的值得到准确的判断结果。

    如果仅仅使用 break ,在循环结束后,无法直接确定 n 是不是质数,还需要通过其他复杂的方式来判断循环是因为找到了因数而结束,还是正常结束。使用 isPrime 变量可以使代码的逻辑更加清晰和易于理解。

例如,如果 n = 15 ,当 i = 3 时,15 % 3 == 0 ,此时就将 isPrime 设为 0 ,并结束循环,因为已经确定 15 不是质数。

答疑

:为什么for循环里,表达式2不可以直接写成i < n

:如果将循环条件写成 i < n ,那么循环会从 2 一直检查到 n - 1

这样做虽然也能判断 n 是否为质数,但是效率相对较低。因为实际上,只需要检查到 i * i <= n 就足够了。

例如,对于数 100 ,如果我们已经检查到了 11 (因为 11 * 11 = 121 > 100 ),就不需要再检查 1299 了,因为如果 100 能被大于 11 的数整除,那么对应的另一个因数一定小于 11 ,而这个小于 11 的因数在之前的循环中就应该已经被检查到了。

所以,将循环条件写成 i * i < n 可以减少不必要的检查,提高程序的运行效率。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值