【问题标题】:Modifying the Prime Number Sieve in C修改 C 中的素数筛
【发布时间】:2019-03-02 23:18:48
【问题描述】:

埃拉托色尼筛法有很多在线实现。通过谷歌搜索,我找到了this implementation in C

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

#define limit 100 /*size of integers array*/ 

int main(){
    unsigned long long int i,j;
    int *primes;
    int z = 1;

    primes = malloc(sizeof(int) * limit);  

    for (i = 2;i < limit; i++)
        primes[i] = 1;

    for (i = 2;i < limit; i++)
        if (primes[i])
            for (j = i;i * j < limit; j++)
                primes[i * j] = 0;

    printf("\nPrime numbers in range 1 to 100 are: \n");
    for (i = 2;i < limit; i++)
        if (primes[i])
            printf("%d\n", i);

return 0;
}

然后我尝试更新现有代码,以便 C 程序遵循 Scott Ridgway 在Parallel Scientific Computing 中描述的内容。在第一章中,作者描述了所谓的素数筛。修改后的筛子不是在 k

为了匹配作者提供的伪代码,我修改了上面的原程序并写了

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

#define limit 10 /*size of integers array*/

int main(){
    unsigned long long int i,j,k;
    int *primes;
    int *arr[100];
    int z = 1;

    primes = malloc(sizeof(int) * limit);

    for (i = 2;i < limit; i++)
        primes[i] = 1;

    for (i = 2;i < limit; i++)
        if (primes[i])
            for (j = i;i * j < limit; j++)
                primes[i * j] = 0;

    /* Code which prints out primes for Sieve of Eratosthenes */
    /*printf("\nPrime numbers in range 1 to 100 are: \n");

    for (i = 2;i < limit; i++)
        if (primes[i])
            //printf("Element[%d] = %d\n", i, primes[i]);*/

    for (k=limit; k < limit*limit; k++)
        for (j = primes[0]; j = arr[sizeof(arr)/sizeof(arr[0]) - 1]; j++)
            if ((k % j) == 0)
                arr[k]=0;
        arr[k] = 1;

    printf("\nPrime numbers in range k to k^2 are: \n");
    for (k=limit; k < limit*limit; k++)
        if (arr[k])
            printf("Element[%d] = %d\n", k, k);

return 0;

}

返回

Prime numbers in range k to k^2 are:
Element[10] = 10
Element[14] = 14
Element[15] = 15
Element[16] = 16
Element[17] = 17
Element[18] = 18
Element[19] = 19
.
.
.

这显然是错误的。我认为我的错误在于我对伪代码的解释

作为

for (k=limit; k < limit*limit; k++)
            for (j = primes[0]; j = arr[sizeof(arr)/sizeof(arr[0]) - 1]; j++)
                if ((k % j) == 0)
                    arr[k]=0;
            arr[k] = 1;

由于我是 C 新手,我可能犯了一个基本错误。我不确定上面的五行代码有什么问题,因此在 Stack Overflow 上提出了一个问题。

【问题讨论】:

  • 我根本没有进入算法,但很明显,在第二个 for 语句中,您有一个赋值给 j,而不是在语句的条件部分进行比较。
  • 是的,我也注意到了这一点。就在这里:j = arr[sizeof(arr)/sizeof(arr[0]) - 1];
  • 此外,您可能需要大括号作为外部循环的主体,以便语句 arr[k] = 1; 是循环的一部分。现在不是在代码结构让它相信它的时候。

标签: c primes


【解决方案1】:

你的循环语句有问题,j 变量应该用于primes 的索引,它是指向具有 0 或 1 值的 int 数组的指针。在这种情况下,您可以使用primes 数组是算法中的 S(k)。

for (k=limit; k < limit*limit; k++)
        for (j = primes[0]; j = arr[sizeof(arr)/sizeof(arr[0]) - 1]; j++)
            if ((k % j) == 0)
                arr[k]=0;
        arr[k] = 1;

所以j的for循环应该是

for (j = 2; j < limit; j++)

and condition IN if 语句应该是

if (primes[j] && (k % j) == 0)
{
    arr[k] = 0;
    break;
}

如果这个条件成立,我们应该退出带有j变量的内部for循环。在带有j 的for 循环之外,应检查j 变量的值以检查内部循环是否完成(j == limit)

if (j == limit) arr[k] = 1;

所以这是我修改的整个 for 循环(外循环和内循环)。

for (k = limit; k < limit*limit; k++)
{
    for (j = 2; j < limit; j++)
    {
        if (primes[j] && (k % j) == 0)
        {
            arr[k] = 0;
            break;
        }
    }
    if (j == limit) arr[k] = 1;
}

这是完整的解决方案:

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

#define limit 10 /*size of integers array*/

int main() {
    unsigned long long int i, j, k;
    int *primes;
    int arr[limit*limit];
    int z = 1;

    primes = (int*)malloc(sizeof(int) * limit);

    for (i = 2; i < limit; i++)
        primes[i] = 1;

    for (i = 2; i < limit; i++)
        if (primes[i])
            for (j = i; i * j < limit; j++)
                primes[i * j] = 0;

    /* Code which prints out primes for Sieve of Eratosthenes */
    /*printf("\nPrime numbers in range 1 to 100 are: \n");

    for (i = 2;i < limit; i++)
        if (primes[i])
            //printf("Element[%d] = %d\n", i, primes[i]);*/

    for (k = limit; k < limit*limit; k++)
    {
        for (j = 2; j < limit; j++)
        {
            if (primes[j] && (k % j) == 0)
            {
                arr[k] = 0;
                break;
            }
        }
        if (j == limit) arr[k] = 1;
    }

    printf("\nPrime numbers in range k to k^2 are: \n");
    for (k = limit; k < limit*limit; k++)
        if (arr[k] == 1)
            printf("Element %d\n",  k);

    return 0;

}

【讨论】:

    猜你喜欢
    • 2015-05-07
    • 2017-09-25
    • 2011-03-06
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    相关资源
    最近更新 更多