Home > Net >  I don't understand why my program to find prime numbers is working?
I don't understand why my program to find prime numbers is working?

Time:03-17

I'm currently learning C and I just created a simple program to find prime numbers :

#include <iostream>
using namespace std;
main() {


// VARIABLES

int num = 3;
int divisor = 2;
const int max = 1000000;
bool prime = true;

// BOUCLE

while (num <= max) {
    while (divisor <= (num / 2)) {
        if ( (num % divisor) == 0) {
            prime = false;
            divisor = 2;
            break;
        }
        divisor  ;
    }
    if (prime == true) {
        cout << num << endl;
    }
prime = true;
num  ;
}
}

My question is about the divisor integer : if the number tested is not prime, the "divisor = 2" line is never executed, so how is my loop working fine? Example : 11 is tested. 11 is a prime number, so the if statement is never executed, but the int divisor value is now 5. Then 12 is tested, starting with the divisor 5. This should cause an error, no?

CodePudding user response:

The reason this works is number theory: you're testing all the even numbers too, and that will always reset your divisor down to 2, ready to do the next test on an odd number (which may or may not be prime).

So let's go past 11 and 12, and go to 13. Your loop will break out of that with a divisor value of 7 and (correctly) mark 13 as prime. Then it'll increment num to 14, and that test will go into your prime=false; section, resetting divisor to 2. Bottom of the loop, testing for 15 now. And the divisor was reset to 2 and you're good, since your code will cycle through 3 as the divisor and 15 will be marked as non-prime (correctly). Then 16 will reset divisor again, ready for 17. Etc.

If you were more clever and only testing odds (if it was num =2 not num at the end), then this case would actually break, since 7 is above the largest factor of 15, and would erroneously say prime. But because you are testing even numbers, and at worst divisor will be half of the number, it'll get reset.

CodePudding user response:

When you find a composite number, you reset divisor to 2, so that's not a problem.
(It is very unclear why you believe that line isn't executed – is that a typo?)

When you find a prime, the next num is going to be even, and the first divisor you test is num / 2 (when you're "done" with 11, the first divisor is 6, not 5).

And since num is even, num / 2 divides num (if a divides b, then so does b/a).

CodePudding user response:

how is my loop working fine?

Code only resets the initial divisor to 2 when a non-prime is found, but not when a prime is found.

    // When true, `num` is _not a prime.
    if ( (num % divisor) == 0) {
        prime = false;
        divisor = 2;
        break;
    }

Normally the divisor = 2; should happen before each new num.

Since code is incrementing, after a prime is found the next num is even and that eventually (num % divisor) == 0 is true. Thus resetting things properly.

A better prime test for reference.

  while (num <= max) {
    // Set first divisor here
    int divisor = 2;
    prime = true;
    // Iterate to the sqrt, not num/2 --> much faster
    while (divisor <= num / divisor) {
      if (num % divisor == 0) {
        prime = false;
        break;
      }
      divisor  ;
    }
    if (prime && num > 3) {
      cout << num << endl;
    }
    num  ;
  }
  • Related