C program which prints the Germain primes in a range received by user

Viewed 708

For integers X and Y received from the user (assuming X < Y), write the program that adds all Germain prime numbers in the range of X to Y to an array and prints the elements in this array on the screen. Germain prime numbers are primes such that the number 2p + 1 is also prime. An additional string will not be used in this question. Otherwise, it will be evaluated as 0.

Sample:

Enter X and Y: 2 15
Germain Prime Numbers in the Range: 2-3-5-11

I have a question like that. I wrote a program but it was printing some wrong numbers, too. However, it doesn't print anything now

Here is my code:

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

int main() {
    int x, y, i, j, k, counter = 0, counter2 = 0;

    printf("Please enter x and y values:\n\a");
    scanf("%d %d", &x, &y);

    for (i = x; i <= y; i++) {
        for (j = 1; j <= i; j++) {
            if (i % j == 0) {
                counter++;
            }
        }                        
        if (counter == 2) {                                               
            for (k = 1; k <= 2 * i + 1; k++) {
                if ((2 * i + 1) % k == 0) {
                    counter2++;
                } 
                if (counter2 == 2) {
                    printf("%d is a germain prime number", i);
                }
            }
        }
        counter = 0;
    }
    return 0;   
}

Can someone tell me where my mistake is?

Edit: I shouldn't use the functions created by user

5 Answers

Your code is too complicated. The main loop should be simplified. Furthermore, the output is not what the example shows.

Here are the issues:

  • the loop for (j = 1; j <= i; j++) is a very inefficient inline re-implementation of isPrime().
  • the test if (2 * i + 1 % k == 0) in the second loop should use parentheses: if ((2 * i + 1) % k == 0)
  • counter2 is never reset to 0. It would be safer to set both counter and counter2 to 0 before their respective loops.
  • actually, it would be much better to call isPrime().

Here is a modified version:

#include <stdbool.h>
#include <stdio.h>

bool isPrime(int n) {
    // Corner case
    if (n <= 1)
        return false;
 
    // Check from 2 to square root of n
    for (int i = 2; i <= n / i; i++) {
        if (n % i == 0)
            return false;
    }
    return true;
}

int main() {
    int x, y, i, counter = 0;

    printf("Enter X and Y: ");
    if (scanf("%d %d", &x, &y) != 2)
        return 1;

    printf("Germain Prime Numbers in the Range: ");
    for (i = x; i <= y; i++) {
        if (isPrime(i) && isPrime(2 * i + 1)) {
            counter++;
            if (counter > 1)
                putchar('-');
            printf("%d", i);
        }
    }
    printf("\n");
    return 0;   
}

If you cannot use function, which is a strange requirement, you can expand the code inside the main function:

#include <stdio.h>

int main() {
    int x, y, counter = 0;

    printf("Enter X and Y: ");
    if (scanf("%d %d", &x, &y) != 2)
        return 1;

    printf("Germain Prime Numbers in the Range: ");
    for (int n = x; n <= y; n++) {
        int isprime = (n >= 2);
        for (int i = 2; i <= n / i; i++) {
            if (n % i == 0) {
                isprime = 0;
                break;
            }
        }
        if (isprime) {
            int isgermain = 1;
            for (int i = 2, n2 = 2 * n + 1; i <= n2 / i; i++) {
                if (n2 % i == 0) {
                    isgermain = 0;
                    break;
                }
            }
            if (isgermain) {
                counter++;
                if (counter > 1) {
                    putchar('-');
                }
                printf("%d", n);
            }
        }
    }
    printf("\n");
    return 0;   
}

Here is an alternative method using a simplistic sieve of Eratosthenes. It finds all Sophie Germain primes below 109 in less than 30 seconds:

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

int main(int argc, char *argv[]) {
    int x, y, counter = 0;

    if (argc > 1) {
        x = y = strtol(argv[1], NULL, 0);
        if (argc > 2) {
            y = strtol(argv[2], NULL, 0);
        }
    } else {
        printf("Enter X and Y: ");
        if (scanf("%d %d", &x, &y) != 2)
            return 1;
    }
    int max = 2 * y + 1;
    unsigned char *composite = calloc(max + 1, 1);
    if (composite == NULL) {
        printf("out of memory\n");
        return 1;
    }
    composite[0] = 1;
    composite[1] = 1;
    for (int p = 2; p * p <= max; p++) {
        if (composite[p])
            continue;
        for (int i = p * p; i <= max; i += p)
            composite[i] = 1;
    }
    for (int p = x; p <= y; p++) {
        if (composite[p] || composite[2 * p + 1])
            continue;
        counter++;
        //printf("%d\n", p);
    }
    free(composite);
    printf("Count of Germain primes between %d and %d: %d\n", x, y, counter);
    printf("approximation for count to %d: 10+1.6*N/log(N)²=%.2f\n",
           y, 10 + 1.6 * y / (log(y) * log(y)));
    return 0;
}

The "issue" is that you never reset your counter2 variable and if (2 * i + 1 % k == 0) needs parentheses. The real issue is that you have implemented the isPrime functionality three times instead of just implementing it once and calling it two times, leading you to be lost in the unnecessary levels of complexity.

Don't have much time to debug your code. But you can run this:

#include <stdio.h>
#include <stdbool.h>

bool isPrime(int n)
{
    // Corner case
    if (n <= 1)
        return false; // Check from 2 to n-1
    for (int i = 2; i < n; i++)
        if (n % i == 0)
            return false;
    return true;
}

bool isGermanPrime(int n)
{
    return isPrime(n) && isPrime(n*2+1);
}

int main()
{
    int x, y;
    // printf("Please enter x and y values:\n\a");
    // scanf("%d %d", &x, &y);
    x = 2;
    y = 15;

    for (int i = x; i <= y; i++)
    {
        if (isGermanPrime(i))
            printf("%d ", i);
    }
    return 0;
}

//OUTPUT
2 3 5 11 
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

bool isPrime(int n) {
    // Corner case
    if (n <= 1)
        return false;
 
    // Check from 2 to n-1
    for (int i = 2; i < n; i++)
        if (n % i == 0)
            return false;
 
    return true;
}

int main() {
    int x, y;

    printf("Please enter x and y values:\n\a");
    scanf("%d %d", &x, &y);

    for (int p = x; p < y; p++) {
        if (isPrime(p) && isPrime(2 * p + 1)) {
            printf("%d is a germain prime number\n", p);
        }
    }

    return 0;
}

"Write the program that adds all Germain prime numbers in the range of X to Y to an array and prints the elements in this array on the screen." And also "I shouldn't use the functions created by user". Here it is

#include <stdio.h>

#define SIZE 100

int main() {

    int x, y, germ, prime, gPrime;
    int n[SIZE], count = 0, i, j;

    scanf("%d%d", &x, &y);

    if( x < 3 ) {

        n[0] = 2;
        ++count;
        x = 3;
    }
    else if( !(x % 2) ) {
        
        ++x;
    }

    for(i = x; i <= y; i += 2) {

        prime = 1;
        gPrime = 1;
    
        for(j = 3; j < i; y += 2) {
        
            if( !(i % j) ) {
            
                prime = 0;
                break;
            }
        }
    
        if( prime ) {
    
            germ = 2 * i + 1;
        
            for(j = 3; j < germ; j += 2) {
            
                if( !(germ % j) ) {
                
                    gPrime = 0;
                    break;
                }
            }
        
            if( gPrime ) {
            
                n[count] = i;
                ++count;
            }
        } // end outer if
    }

    for(i = 0; i < count; i++) {
    
        printf("%d ", n[i]);
    }

    return 0;
}

Note: the compiler I use on my phone has a time limit that won't let me see the output. I hope the program works.

Related