Reputation: 67
I am trying to check whether a given number is prime but I've run into an issue. This is the code:
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
bool isPrime(int input)
{
for (int i = sqrt(input); i >= 2; i--)
{
if (input % i == 0)
{
return false;
}
return true;
}
}
int main()
{
int input;
scanf("%d", &input);
if (isPrime(input))
{
printf("Is prime number");
} else
{
printf("Is not prime number");
}
return 0;
}
In the code block of my isPrime
function, if I put return true;
in the for loop like above, this will be wrong in some cases (for example, when input
is 10, it will declare that 10 is a prime number). But if I put return true;
outside the for loop, it works fine. So what is the difference?
Upvotes: 0
Views: 605
Reputation: 310960
The function returns true if the first divisor in the for loop does not divide the target number.
because this return statement
return true;
is inside the for loop.
bool isPrime(int input)
{
for (int i = sqrt(input); i >= 2; i--)
{
if (input % i == 0)
{
return false;
}
return true;
}
}
Moreover the function has undefined behavior if it is called for example for prime numbers 2
or 3
or if a non-positive number is passed to the function.
Placing the return statement
return true;
outside the loop does not make your function correct.
Pay attention to that there is no sense to check even numbers except the number 2
whether they are prime or not prime.
The function can be written the following way
bool isPrime( unsigned long long n )
{
bool prime = n % 2 == 0 ? n == 2 : n != 1;
for ( unsigned long long int i = 3; prime && i <= n / i; i += 2 )
{
prime = n % i != 0;
}
return prime;
}
The function can be called like
unsigned int input;
scanf("%u", &input);
if (isPrime(input))
{
printf("Is prime number");
} else
{
printf("Is not prime number");
}
Upvotes: 1
Reputation: 123458
Let's walk through your loop:
for (int i = sqrt(input); i >= 2; i--)
{
If the input is 10
, then i
starts out as 3
(remember that when assigning a floating-point value to an int
, the fractional portion is discarded). 3
is greater than or equal to 2
, so the loop body executes.
if (input % i == 0)
{
The remainder of 10
divided by 3
is not zero, so we do not enter the body of the if
statement.
return false;
}
return true;
}
And then we immediately return true
.
Because of this, no matter what input you provide, your loop will only iterate 1 time. If input
is evenly divisible by the integer value of its square root (such as 9
, 16
, or 25
), then the body of the if
statement is executed and it returns false
, otherwise it unconditionally returns true
.
For your function to work properly, you must move the return true;
statement outside the body of the loop - you should only return true
when you've exhausted all values of i
between sqrt(input)
and 2
.
Upvotes: 1
Reputation: 314
This happens because your for loop isn't over with the complete traverse of i, but the return true
statement tells the code to execute it the very first time your if condition goes false, and then exit the loop. So, imagine I give you 10 chocolate bars and tell you to take a bite from each, and only collect the dark ones. You take a bite on the first, it's sweet, you put it away. You take a bite on the second and it's dark. You collect it and you tell me you are done, although you actually aren't (You didn't check the rest of the chocolate bars to see if there are more dark ones there or not). That's what you are doing in your code. Hope the example is clear and helpful :)
Upvotes: 0
Reputation: 6740
When you put return true;
inside of the loop, that statement will be executed whenever the preceding if
condition is false. You only want to return true
once you've completed your for
loop and have found no divisors. That's why the return
statement needs to be outside the loop.
Upvotes: 0