如何在 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_factor
和 n%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 伪代码。
首先,本人对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_factor
和 n%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 伪代码。