【问题标题】:Printing prime numbers using arrays使用数组打印素数
【发布时间】:2022-01-24 23:03:16
【问题描述】:

这是打印素数的代码。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

int main()
{
    int p;   
    int i;
    int primes[50] = { 0 };
    int primeIndex = 2;
    bool isPrime;

    // hardcode prime numbers
    primes[0] = 2;
    primes[1] = 3;

    for (p = 5; p <= 100; p = p + 2) {
        isPrime = true;

        for (i = 1; isPrime && p / primes[i] >= primes[i]; ++i)
            if (p % primes[i] == 0)
                isPrime = false;

        if (isPrime == true) {
            primes[primeIndex] = p;
            ++primeIndex;
        }
    }

    for (i = 0; i < primeIndex; ++i)
         printf ("%i  ", primes[i]);

    printf("\n");
    return 0;
}

这段代码有几处我不明白:

内部for循环中的条件如何工作以及isPrime变量的用途是什么?

【问题讨论】:

  • 布尔值是在找到第一个除数时终止循环。如果候选人被证明不是素数,那么找到另一个除数就没有意义了。另一个条件p / primes[i] &gt;= primes[i] 是防止它迭代超出候选的平方根。为什么?假设p15。我们会发现3 是一个除数,所以继续测试5 是没有意义的。
  • 硬编码 2 是有意义的,因此 p 可以以 2 为步长递增(仅尝试奇数)并以 i=1 开头因此是有意义的,因为无需测试 2 是否为除数。硬编码 3 对我来说没有意义。顺便说一句,这个问题讨论了完全相同的代码:stackoverflow.com/questions/69764736/…
  • 使用牙套——它可以防止你被裤子夹住

标签: arrays c boolean


【解决方案1】:

代码正确计算并打印所有小于或等于 100 的素数。

为什么需要硬编码 2 个素数(2 和 3)?

2 是一个特例:它是唯一的偶素数。 2 被硬编码为第一个素数,因此外部循环仅测试奇数。

3 是硬编码的,因此外部循环可以依赖数组内容作为其停止条件p / primes[i] &gt;= primes[i]。数组中至少需要有一个奇质数,以避免对数组索引进行额外测试,例如i &lt; primeIndex

正如 chux 所评论的,内部循环可以从索引 i = 0 开始,然后只需将 2 硬编码到数组中。筛选过程的效率会稍低一些,因为所有数字都将不必要地被测试为可被 2 整除,这可以跳过,因为所有测试的数字都是奇数。

第一个for循环中的布尔表达式有什么用?

第一个for 循环中的条件测试是p &lt;= 100。该程序枚举低于或等于100 的素数。 primes 数组的长度为 50,对于这个范围来说已经足够了。如果范围更大,则需要扩展数组大小。

布尔变量isPrime用于存储素性检验的结果。它被初始化为true,当且仅当在内循环中找到一个素数除数时,它才会被重置为false

在内循环之后测试变量以检查是否应将p附加到素数列表中。

第二个for 循环isPrime &amp;&amp; p / primes[i] &gt;= primes[i] 中的条件是一种优化:它允许循环在找到除数时立即停止。这个测试可以简化为p / primes[i] &gt;= primes[i],循环将继续测试素数除数,直到p 的平方根。在找到除数时添加break 语句是一种提前停止循环以提高效率的替代方法。

谁能解释一下内部 for 循环是如何工作的?

内部循环迭代素数除数,直到发现一个余数为 0 (p % primes[i] == 0) 或直到除数大于 p 的平方根 (p / primes[i] &gt;= primes[i])。

注意数组primes不需要初始化。

这是一个简化版:

#include <stdio.h>
#include <stdbool.h>

int main() {
    int primes[50];
    int i, p, primeIndex;

    // hardcode 2 prime numbers
    primes[0] = 2;
    primes[1] = 3;
    primeIndex = 2;

    // enumerate odd numbers from 5 to 100
    for (p = 5; p <= 100; p = p + 2) {
        // use a boolean variable that will be set to false if p is composite
        bool isPrime = true;

        // test all odd prime divisors up to the square root of p
        for (i = 1; p / primes[i] >= primes[i]; ++i) {
            if (p % primes[i] == 0) {
                isPrime = false;
                break;
            }
        }
        // if p is prime, add it to the array.
        if (isPrime) {
            primes[primeIndex++] = p;
        }
    }

    for (i = 0; i < primeIndex; ++i)
         printf("%i  ", primes[i]);

    printf("\n");
    return 0;
}

这是一个使用函数的更简单的版本:

#include <stdio.h>
#include <stdbool.h>

// test if an odd number greater than 3 is a prime
bool isOddPrime(int p, const int *primes) {
    for (int i = 1; p / primes[i] >= primes[i]; ++i) {
        if (p % primes[i] == 0)
            return false;
    }
    return true;
}

int main() {
    int primes[50] = { 2, 3 };  // hardcode 2 prime numbers
    int primeIndex = 2;

    for (int p = 5; p <= 100; p = p + 2) {
        if (isOddPrime(p))
            primes[primeIndex++] = p;
    }

    for (i = 0; i < primeIndex; ++i)
         printf("%i  ", primes[i]);

    printf("\n");
    return 0;
}

【讨论】:

  • 在内部 for 循环 p/prime[i]>= prime[I] 中,如果我们使用这些值,它将变为 5(p)/ 3(prime(1) >= 3 primes(1 ). 这个循环应该终止后。为什么它不终止循环?
  • 不同意“数组中必须至少有一个奇质数”中的需要。可以使用primes[0] = 2; for (p = 3; p &lt;= 100; p = p + 2) { isPrime = true; for (i = 0; ...
  • @Deepak:p=5 的第一次迭代以测试 5 / 3 &gt;= 3 开始,这是错误的,因此循环停止并且不执行主体,isPrime 保持 true,即正确,因为 5 是素数。
  • @chux-ReinstateMonica:你是绝对正确的。我会完善答案。
  • 所以我们必须假设存储在 P 中的每个值都是素数,直到它在 if 语句中被证明是错误的?对于 ex - p = 9 , 9 / 3 (prime[1] = 3 并且余数为 0。余数为零并且 isPrime 变为 false 对吗?
猜你喜欢
  • 2011-03-23
  • 2010-12-30
  • 2012-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多