如何在 C 中实现更快的素数搜索算法

How to Implement a Faster Algorithm for Searching for Primes in C

首先,本人对C比较陌生,对C++一窍不通,只学过w3schools.org tutorial on C, and made a few practice programs. What I am looking for is something simple that can find all primes form 1 to 1000000 in under half an hour. I do not know how to implement anything complex like Sieve of Atkin等复杂的算法。您能否更简单地解释阿特金筛法(如外行人的术语)或用 C 语言进行演示?请记住,我刚刚从 w3schools 学习了 C 语言的初级课程。

我使用的代码如下:

#include <stdio.h>

int n = 0, i, b, e, flag = 0;

int main() {
    printf("Enter a positive integer that will be the higher bound: ");
    scanf("%d", &b);

    for (n = 0; n < b; n++) {
        if (n == 0 || n == 1) {
        flag = 1;
        }
      for (i = 2; i <= n / 2; ++i) {
        if (n % i == 0) {
          flag = 1;
        }
      }
      if (flag == 0) {
        printf("%d is a prime number.\n", n);
        } else {
        }
        flag = 0;
    }
  return 0;
}

OP 的代码使用 for (i = 2; i <= n / 2; ++i) { 限制因素测试 - 适度的第一步。

但是超过 n 的平方根,没有因数。由于根(通常)比 n/2 小,因此 很多。

我们可以使用 test_factor * test_factor <= n,但 test_factor * test_factor 可能会溢出。使用 test_factor <= n/test_factor。聪明的编译器会看到附近的 n/test_factorn%test_factor 并发出执行速度与其中一个一样快的代码。

代码可以计算 int limit = sqrt(n),但是 1) 存在边缘情况问题,因为 sqrt() 可能没有 return 完全 追捧的根即使它是整数 2) 当整数类型的精度高于 double 时,也可能会丢失所需的岁差。 3) 产生浮点成本,而 test_factor <= n/test_factor.

几乎没有额外成本

OP 的代码会在找到一个因素时设置一个标志,然后继续寻找更多因素。然而,没有理由继续寻找。一旦找到一个因素,这会大大加快退出循环的速度。

我们还可以检查所有其他值,因为数字除以 2 不是质数 - 除了一个例外:2。这是一个 适度 改进。

bool is_prime(int n) {
  if (n % 2 == 0) {
    return n == 2;
  }
  for (int test_factor = 3; test_factor <= n / test_factor; test_factor += 2) {
    if (n % test_factor == 0) {
      return false;
    }
  }
  return n > 1;  // No factors and n is more than 1.
}

使用

for (n = 2; n < b; n++) {
  if (is_prime(n)) {
    printf("%d is a prime number.\n", n);
  }
}

注意:不到2秒打印出所有小于1000000的素数


对于筛选方法。请参阅 Sieve of Eratosthenes 伪代码。