Question

I want to use a bit-array and the Sieve of Eratosthenes algorithm to find all the primes within a certain range. My code compiles, but it prints all the non-prime numbers rather than prime numbers (except for 2 because I ask my Sieve function to print 2). Can someone review my code and give me some hints on how to fix it? Your help is greatly appreciated. Thank you!

Note: The requirement of my homework is to use a bit-array.

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

//#define MAXBYTES 1000000
#define MAXBYTES 10


void setBit(unsigned int A[], int k);
unsigned getBit(unsigned int A[], int k);
void print_prime (int prime_num);
void sieve_Prime(unsigned int bit_arr[]);

int main (int argc, char** argv)
{
    //int bit_arr[MAXBYTES];      //This is the bit array (32 X MAXBYTES)
    unsigned int bit_arr[MAXBYTES];      //or bit_arr[MAXBYTES]
    int i;

    for (i=0; i < MAXBYTES; i++)
    {
        bit_arr[i] = 0x00;            //initialize all bits to 0s
    }

    setBit(bit_arr, 0);             //0 is not prime, set it to be 1
    setBit(bit_arr, 1);             //1 is not prime, set it to be 1

    sieve_Prime(bit_arr);
    printf("\n");

    return 0;

}

//Set the bit at the k-th position to 1
void setBit(unsigned int A[], int k)
{
    int i = k/32;
    int pos = k % 32;

    unsigned int flag = 1;      //flag = 0000 ..... 00001
    flag = flag << pos;         //flag = 0000...010...000 (shifted k positions)

    A[i] = A[i] | flag;         //Set the bit at the k-th position in A[i];
}

//get the bit at the k-th position
unsigned getBit(unsigned int A[], int k)
{
    int i =k/32;
    int pos = k % 32;

    unsigned int flag = 1;

    flag = flag << pos;

    if (A[i] & flag)
        return 1;
    else
        return 0;
}


void print_prime (int prime_num)
{
    //print a prime number in next of 8 columns
    static int numfound=0;

    if (numfound % 8 == 0)
        printf("\n");
    if (prime_num+1 < MAXBYTES*8)
        printf("%d\t", prime_num);
    numfound++;
}

void sieve_Prime(unsigned int bit_arr[])
{
    int i;
    int k;
    int next_prime = 2;

    print_prime(2);

    while (next_prime+1 < MAXBYTES*8)
    {
        k = next_prime;

        //multiples of next_prime is not primpe
        while(next_prime*k < MAXBYTES*8)
        {
            setBit(bit_arr, next_prime*k);      //set it to be 1
            k++;     
        }

        //find next_prime by skipping non-prime bits marked 1
        while (next_prime + 1 < MAXBYTES*8 && getBit(bit_arr, ++next_prime))
        {
            print_prime(next_prime);
        }
    }
}
Was it helpful?

Solution

The problem is your loop:

while (next_prime + 1 < MAXBYTES*8 && getBit(bit_arr, ++next_prime))
{
    print_prime(next_prime);
}

Your keeping printing things while the bit is set (i.e. while you know it's not a prime). So basically, your loop is "print all the numbers I find while looking for the next prime" rather than "look for the next prime in a loop, then print the next prime".

I suspect you want something like:

next_prime++; // We always want to at least move on once...
while (next_prime + 1 < MAXBYTES*8 && getBit(bit_arr, next_prime))
{
    next_prime++;
}
print_prime(next_prime);

I haven't checked whether that's all that was wrong with the code, but it's certainly an initial thing to fix.

OTHER TIPS

You may init the array with zero values simply by adding the next initialization construct:

unsigned int bit_arr[MAXBYTES] = { };

Then each member of the array will hold zero value. Also, try to avoid the things such as printf("\n");. It is better to use putchar('\n') if you need only to output one symbol at a time.

Additionally, you may add the static keyword to your working function prototypes and definitions except the main function if you'll not use this routines outside this translation unit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top