Hello i'm new learner at java, the tutor on Udemy gave us this method but he didn't explain it, i found it hard to understand, and i tried to execute it, but still the same thing.
PS : sorry for my English i'm Arabian.
This is the method:
public static boolean isPrime(int n) {
if(n == 1) {
return false;
}
for(int i = 2; i <= n/2; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
The code loops through all numbers from 2 to n/2 and checks if n is divisible by that number. If it is divisible by any of these numbers the function returns false as n has a divisor. If we have found no divisor from 2 to n/2 the number is prime. A better approach would be to loop to the square root of n.
The method isPrime(int n) takes an integer n and checks whether it is prime or not.
First it checks whether n is equal to 1. If it is the method returns false, because 1 is not prime.
Afterwards it loops through all the numbers between 2 and n/2, and checks if n is divisible by that number. If it is, the method returns false because then it is not prime.
The reason why it does not check every number from 2 til n is because it would be redundant. The number n can never be expressed as a product of a whole number and a number that is bigger than n/2, except n but then it would not be a prime number.
Related
I'm writing this problem for school and I have some issues with it. I can't get it to actually calculate the prime number. Obviously, when I run a test from main with the number 4 it says 4 is a prime number when we all know it's not. How do I need to write out the equation?
The instructions are as follows.
Use RECURSION to write this function (or make this function a wrapper over another recursive function)
* a number is prime if it is divisible only by itself and 1
* (that is, if it is not divisible by any number between * itself and 1;
* we can optimize and just check between 2 and the square root of the number).
* by convention, 1 is NOT prime
* this function returns true if its parameter is prime, false otherwise.
* One way to do this is to test all numbers between 2 and n; if any of them
* divides it, then it is not prime. If you reach the end, then it is.
* Examples:
* isPrime(1) => false
* isPrime(2) => true
* isPrime(3) => true
* isPrime(4) => false
*/
public static boolean isPrime(int n)
{
if (n == 0 || n == 1) {
return false;
} if (n == 2 || n == 3) {
return true;
} if (Math.sqrt(n) % 2 == 0) {
return true;
}else
return isPrime(n);
}
The below code is from the grader.java that my prof uses to grade the program. There are a few calls to the isprime method. It always seems to get hung up on 4 (I see why... 4 squared % 2 == 0) and 4 isn't a prime #.
public void testIsPrime()
{
Assert.assertEquals("1 is not prime", false,Assignment4.isPrime(1));
Assert.assertEquals("2 is prime", true,Assignment4.isPrime(3));
Assert.assertEquals("4 is not prime", false,Assignment4.isPrime(4));
Assert.assertEquals("7 is prime", true,Assignment4.isPrime(7));
Assert.assertEquals("9 is not prime", false,Assignment4.isPrime(9));
Assert.assertEquals("35 is not prime", false,Assignment4.isPrime(35));
Assert.assertEquals("37 is prime", true,Assignment4.isPrime(37));
}
The assignment is giving you a vital hint:
or make this function a wrapper over another recursive function
public static boolean isPrime_helper(int number, int divisor)
{
/* write code to return true if divisor is > square root of number */
/* which can also be expressed divisor squared is > number */
/* write code here to test if divisor divides number without remainder */
/* and return false if it does. Otherwise: */
return isPrime_helper(number, divisor + 2);
}
public static boolean isPrime(int number)
{
/* deal with the special cases 2, < 2, and even numbers here */
/* Otherwise: */
return isPrime_helper(number, 3);
}
cdlane's answer has the basic correction. I just want to make sure that you know where your try doesn't work. You have two fatal problems:
You have no simplification in your recursion. If you haven't hit the base cases (0-3), you recur with the same number, throwing you into an infinite loop.
Your sqrt clause is both needless and wrong. If the sqrt of a number is even, it cannot be prime. Is this supposed to be a test for stopping the recursion?
In Prime numbers, 2 can't be prime because you can divide it by 2 and it shouldn't be able to divide by 2. Hence, if number%2 is 0 or number is 2 you need to return false.
When a number is not 2 or it's not possible to divide it by 0, you can check for other numbers with a for loop inside your function.
Take a look at following code it helps you to understand what's going on:
public boolean isPrime (int number){
if ((number%2)==0 && number != 2) {
return false;
}
else {
for (int i =3; i*i<number; i++ )
{
if (number%i ==0)
return false;
}
return true;
}
I'm trying to write a function to determine whether a number is "ugly". For a number to be "ugly", it must have no prime factors other than 2, 3, or 5.
Here's my attempt:
public class Solution {
public boolean isPrime(int num) {
if (num == 2) {
return true;
}
if (num % 2 == 0) {
return false;
}
if (num < 0) {
num *= -1;
}
for (int i = 3; i <= Math.sqrt(num); i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
public boolean isUgly(int num) {
if (num < 0) {
num *= -1;
}
for (int i = 7; i <= Math.sqrt(num); i += 2) {
if ((num % i == 0) && isPrime(num)) {
return false;
}
}
return true;
}
}
I'm getting true for input = -2147483648 when it should be false. Is it possible there's an overflow here? I've gone over my code and the logic looks right to me...
Thanks!
The problem is Integer.MIN_VALUE*-1 = Integer.MIN_VALUE leading to Math.sqrt(Integer.MIN_VALUE) which returns NaN on a negative number, so then when you perform this operation 7 <= Math.sqrt(Integer.MIN_VALUE) it returns false and doesn't even enter the for loop resulting in the program returning true.
I hope this explanation helps.
Yeah, I guess so.
Java lower limit for int is -2147483648 and upper 2147483647. As shown in
public class MainClass {
public static void main(String[] arg) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.MIN_VALUE);
}
}
Negative numbers are tricky in such a question.
You have to take the absolute number and factor it. In your original source, you didn't do this. It meant that you got a NaN from the Math.sqrt method. Which also meant that you got false when you compared it to 7.
So your original method would have returned true for all negative numbers.
But changing the sign (which, by the way can be done by num = -num rather than multiplication), which would solve it for all negative numbers, actually introduced an overflow into the program.
The number -2147483648 is, in fact, -231. The maximum positive number allowed in an int is 231-1. So the number - Integer.MIN_VALUE always overflows... into itself. It remains negative after you negate it!
So you run into that NaN again.
But note - since the number is -231, it doesn't, in fact, have any other prime factors other than 2. So the method really should return true for it - assuming that you are not considering -1 a prime.
So I believe that your expectation that it should be false is incorrect - but it depends on the assignment's definition of the prime factors of negative numbers.
Notes:
Your program checks isPrime(num) instead of isPrime(i), and therefore it will always return true. num cannot both be divisible by i and be prime at the same time.
Limiting your program to the square root of num is wrong to begin with. For example, take the number 881305274. Its prime factors are 2 and 440652637. But 440652637 is much bigger than sqrt(881305274). The square root trick works for prime testing, because any factor that is bigger than the root has to be multiplied by a factor that's smaller than the root. But this doesn't apply to the "ugly" problem.
Also, prime numbers are not considered "ugly" as they are a factor of themselves. But your program, because it limits itself to the square root, will never return false for prime numbers.
I came accros one of the solutions for finding if a number is prime as below :
//checks whether an int is prime or not.
boolean isPrime(int n) {
if (n == 2){
return true;
}
//check if n is a multiple of 2
if (n%2==0){
return false;
}
//if not, then just check the odds
for(int i=3;i*i<=n;i+=2) {
if(n%i==0)
return false;
}
return true;
}
What I am trying to understand is this line of code:
for(int i=3;i*i<=n;i+=2)
how does
i*i<=n
help in determining that the number is prime ?
Thanks
This is a logical rule : there is no point to search for other divisors once you pass the square root because at that point your "new" divisors" will be lower than your square root.
Divisors come in pairs: 10 = 2 x 5. Both 2 and 5 are divisors. In each pair one is <= the square root, and the other is >= the square root. 2 <= sqrt(10); 5 >= sqrt(10). Once you have found the 2, there is no need to carry on searching for the 5. 5 = 10 / 2.
eg : 100 :
you check for 2,3,5,7,9, and you stop because if you check for next one (11), 100/11 is 9 and you already checked for 9.
You stop at the square root.
If you find all divisors(including the primes) of n are say a,b,c,d...h.
If a divisor h > sqrt(n) exists, then some divisor c must also exist such that
h * c = n
and since h > sqrt(n) and h * c = sqrt(n) * sqrt(n)
c < sqrt(n).
So, if a divisor greater than sqrt(n) exists than a divisor less than sqrt(n) must also exist and should be able to break the loop before it counts beyond sqrt(n). So, we don't need to count beyond sqrt(n), hence the condition
i*i < n
is imposed.
I am trying to figure out how this Java method calculates a prime number but something is confusing me.
public static boolean isPrime(int number){
for(int divisor =2; divisor <= number / 2; divisor++){
if (number % divisor ==0){
return false;
}
}
return true;
}
As you see in the second line in the for loop it shows divisor <= number /2 instead of divisor <= number. Can anyone tell me the reason for that?
First, if you put divisor <= number, you would get no prime numbers at all, because every number is divisible by itself. If the loop does not exit before divisor becomes number, you would get to
number % divisor == 0
condition, and return false.
Whoever wrote this code made an observation that you can stop as soon as you have reached half the number, because if you did not find divisors in the lower half of the interval (2..number/2), there would be no divisors above half the number either, so you can declare the number prime without trying, unsuccessfully, the rest of the candidate divisors.
However, this is not the best you can do: a stronger condition can be used - you could compare divisor to square root of number. This works, because if you don't have a divisor that is less than or equal to the square root of number, there would be no divisors above the square root as well (it is a good idea to think why this is so).
int stop = Math.sqrt(number);
for(int divisor = 2; divisor <= stop ; divisor++) {
...
}
The reason is is that any number can't be divided by any divisor larger than it's half and give more than 1 (if we are talking integers, of course).
Any number would not be divisible by a number more than its half.
For example, the last number 10 would be divisible is 5. 10 is not divisible with 6, 7, 8 or 9.
This is why it's good to eliminate the obvious mismatches to improve the performance of the algorithm.
As others have noted, there are no factors of n greater than n/2. A better solution is comparing your iterating variable to the square root of n, as if there are no factors less than or equal to the square root, there can't be any greater than the square root (Note that it is more efficient to compare i*i <= n that i <= Math.sqrt(n)).
An even better approach is the AKS primality test. If the number is 2 or 3, then it obviously must be prime. Otherwise, it can be rewritten in the form (6k+i) where i = -1, 0, 1, 2, 3, 4. Any (6k + 2) or (6k + 4) is divisible by 2, and any (6k + 3) is divisible by three, so the prime numbers must either take the form (6k - 1) or (6k + 1).
public static boolean isPrime(long n) {
/* This code uses the AKS primality test
* http://en.wikipedia.org/wiki/AKS_primality_test
*/
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
I used this as a part of my solution to the PrimeCounter problem in Sedgewick's Intro to Programming in Java (although this is in the first chapter before methods are introduced).
public class PrimeCounter {
public static void main(String[] args) {
long n = 10000000;
long count = 0;
for (long i = 0; i <= n; i++) {
if (isPrime(i)) count++;
}
System.out.println("The number of primes less than "
+ n + " is " + count);
}
public static boolean isPrime(long n) {
/* This code uses the AKS primality test
* http://en.wikipedia.org/wiki/AKS_primality_test
*/
if (n <= 3) return n > 1;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i*i <=n; i+=6) {
if (n % i == 0 || n % (i+2) == 0) return false;
}
return true;
}
}
It's using the fact that if one of the factors is greater than N/2 the other must be smaller than 2.
In fact a massive (asymptotic) gain can be obtained by using the square-root.
That's because if one factor is greater than the square root the other is less.
Sorry Sebri Zouhaier. I'm changing allegiance.
The +1 isn't necessary so the best answer is below.
I'm sorry to change sides for such a tiny improvement!
A number N cannot have any divisors D that are > N/2 and < N. To see this, note that if D is a divisor of N, then it must equal N/D2 for some D2. So the divisors of N are those values of this sequence that are integers: N, N/2, N/3, ... This is a descending sequence. It should be obvious that there can't be any divisors between N and N/2.
In fact, it's common for programs that check for primality to stop at sqrt(N) instead of N/2. The reason is this: Suppose there's a divisor D such that D > sqrt(N). Then N/D = D2 also must be a divisor of N. And it must be the case that D2 < sqrt(N), because if both D and D2 were > sqrt(N), then D * D2 would have to be > N, which is wrong because D * D2 = N. This means that there is no need to check possible divisors D > sqrt(N); if such a divisor existed, we already would have found D2 earlier in the loop and proven that N was not prime.
One small caveat to some of the above answers is that 0 and 1 are not prime numbers. You could account for this (for positive integers) with an implementation such as
public static boolean isPrime(int number){
if (number == 0 || number == 1)
return false;
else
{
int stop = (int) Math.sqrt(number);
for (int divisor = 2; divisor <= stop ; divisor++)
{
if (number % divisor ==0)
return false;
}
return true;
}
}
public static Boolean isPrime(int num){ //method signature. returns Boolean, true if number isPrime, false if not
if(num==2){ //for case num=2, function returns true. detailed explanation underneath
return(true);
}
for(int i=2;i<=(int)Math.sqrt(num)+1;i++){ //loops through 2 to sqrt(num). All you need to check- efficient
if(num%i==0){ //if a divisor is found, its not prime. returns false
return(false);
}
}
return(true); //if all cases don't divide num, it is prime.
}
// Returns true iff n is prime. First checks if n is even, handling the
// cases of n=2 (prime) or n is even > 2 (not prime). Then checks if any
// odd #'s between 3 and sqrt(n), inclusive, are divisors of n, returning
// false if any are.
public static boolean isPrime(int n) {
if (n < 2) return false;
if (n % 2 == 0)
// n is an even, so return true iff n is exactly 2
return (n == 2);
for (int i=3; i*i<=n; i+=2)
if (n % i == 0)
// i divides evenly into n, so n is not prime
return false;
return true;
}
This question already has answers here:
Why do we check up to the square root of a number to determine if the number is prime?
(13 answers)
Closed 9 years ago.
How we can use sqrt(n) instead of n/2 in this code? Is it correct to use sqrt(n)?
static boolean isPrime(long n)
{
if(n<=1) return false;
double limit = Math.sqrt(n);
for(long i = 2; i <= limit; i++)
{
if(n%i==0) return false;
}
return true;
}
if n is not a prime, say n = p * q, then p and q cannot be both greater than sqrt(n) (otherwise p*q would be greater than n)
The shown algorithm checks for every integer between 2 and sqrt(n) if n is divisible by it.
If n was divisible by a number greater than sqrt(n), say a, then there would be a factor b so that a * b = n and b < a. In this case the algorithm will find b "first" and see that n is not prime.
Therefore it is not necessary to check any number > sqrt(n).
Perhaps the code would be more understandable (and faster) if you wouldn't use sqrt().
for (long i = 2; i*i <= n; i = (i==2) ? 3 : i+2) {
....
}
Consider ii > n, and n is divisible by i, so that n/i = m. Then m must be smaller than i. But this means your loop must have encountered m earlier already, and found that n is divisible by m. So this means that you find all divisors of n by looping through the range 2..k, where kk <= n.
If you compute a list of prime numbers, you can also take advantage of the fact that if n is not prime, it must be divisible by a prime number. Hence it suffices to check only prime numbers lower or equal than sqrt(n). Since there are much less prime numbers than ordinary numbers in the range, your code will run even faster. You can take the prime numbers from the part of the list you have already computed.