Modifying the Prime Number Sieve in C

巧了我就是萌 提交于 2019-12-12 18:27:10

问题


There are many implementations of the Sieve of Eratosthenes online. Through searching Google, I found 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;
}

I then attempted to update the existing code so that the C program would follow what is described by Scott Ridgway in Parallel Scientific Computing. In the first chapter, the author describes what is known as the Prime number sieve. Instead of finding the primes up to a number k, the modified sieve searches for primes between k <= n <= k^2. Ridgway provides the psuedocode to write this algorithm.

To match the psuedocode provided by the author, I modified the original program above and wrote

#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;

}

which returns

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
.
.
.

This is clearly wrong. I think that my mistake is in my interpretation of the psuedocode

as

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;

As I am new to C, I likely made an elementary mistake. I'm not sure what is wrong with the five lines of code above and have therefore asked a question on Stack Overflow.


回答1:


You have some problem with your loop statement, j variable should use for index of primes that is pointer to array of int with 0 or 1 values. You can use primes array in this case is S(k) in algorithm.

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;

So the for loop with j should be

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

And condition IN if statement should be

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

And if this condition is true, we should exit inner for loop with j variable. Outside for loop with j, should check value of j variable to check if the inner loop is completed or not (j == limit).

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

So here is the entire for loop (outer and inner loop) the I modified.

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;
}

And here is entire solution:

#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;

}


来源:https://stackoverflow.com/questions/54964020/modifying-the-prime-number-sieve-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!