I do not understand the logic behind this number checker and I'm wondering if somebody could help me understand it a little bit better.
Here's the code:
I will do my best to comment on what's happening but I do not fully understand it.
//find prime numbers between 2 and 100
class PrimeNumberFinder {
public static void main(String args[]) {
int i, j; // declare the integer variables "i" and "j"
boolean isPrime; // declare the Boolean variable is prime but do not assign value
// create a for loop that starts at two and stops at 99.
for (i=2; i < 100 ; i++) {
isPrime = true; // I do not know why isPrime is set to true here.
// This is where I get confused badly.. we give the "j" variable a value of two and check to see if it's less than whatever "i" divided by "j" is.
// If "i=2" then how would j (which is = 2) be less than or equal to i/j (2/2)?
for (j = 2; j <= i/j; j++)
if ((i%j) == 0) isPrime = false; // If a certain number goes in evenly that isn't 1, or "i" itself, it isn't prime so we set the boolean to false
if (isPrime) // if true print i
System.out.println(i + " Is a prime number");
}
}
}
As you can see the second for loop and almost everything going on within it confuses me, especially the "j <= i/j" because to me j is always going to be bigger.. and why is "j" even increasing? Can't you just divide it by two and determine whether or not it's prime that way?
Any help is greatly appreciated, thank you for reading.
Let's go through it line by line.
int i, j;
boolean isPrime;
We start with declaring our variables. Nothing too fancy.
for (i=2; i < 100; i++) {
isPrime = true;
Here we enter our loop that basically contains all the number we are going to check (here: 2 - 99). We also state that the current number is a prime number (unless proven otherwise).
for (j = 2; j <= i/j; j++)
if ((i%j) == 0) isPrime = false;
Now here is where the magic happens. We are going to check if we can divide the current number i evenly by any integer ranging from j == 2 to i/j (i/j ultimately is just a fancy way of writing Math.sqrt(i)). So why up until there?
Well, say we have two divisors a and b such that a * b = i. Now, if divisor a is bigger than the square root of i, then the other divisor b will be smaller than the square root of i. If not then a * b > i and this isn't possible.
So, if we can find a case in which we can divide evenly, this explicitly means that the current number is not prime and we set the isPrime variable to false.
if (isPrime) // if true print i
System.out.println(i + " Is a prime number");
}
So, if we still have isPrime == true, it means that the current number withstood our test and we can print it.
Two further improvements;
Once we know the number is not prime, there is no need to check any
additional divisors, so we want to exit the loop and hence a
break; statement could be addded.
2 is the only even prime number, so alternatively you could
start the second loop at j == 3 and increase by 2 after every execution.
You'll then have to consider the case when i == 2 separately.
Related
Very new to programming here, trying to get my head around how this is works and I just cannot seem to do it, spent a good while staring at this one.
code already works, I Just do not fully understand.
class PrimeNum{
public static void main(String[] args) {
int a;
int b;
boolean isprime;
System.out.println("this is a program listing prime numbers up to 100");
for(a = 2; a < 100; a++){
for(b=2; b <= a/b; b++)
```if((a%b) == 0) isprime = false;```
if(isprime)
System.out.println(a + " is prime.");
}
}
}
I think that i understand both for lines, please correct me If I am wrong.
Am I correct in saying that, if a is less than 100, increment
if b is less than or = to a/b then increment again which it always will be
the line that i don't understand is highlighted in particular, what is the need for the ==0?
I just cannot seem to grasp the concept that is happening here and how its figuring out what is and isn't prime.
Okay, we'll start up:
public static void main(String[] args){..}
This is the main method which every Java program should have. You'll get to learn user-defined methods, but that's for later;
We'll skip the variable declaration...
for(a = 2; a < 100; a++){...
}
This first loop gets you a number for deciding for its prime being...
for(b=2; b <= a/b; b++)
if((a%b) == 0)
isprime = false;
Probably b is for division of a...
So if you execute this 6 times for number 2,
it'll go that way, if the remainder got on dividing 2 is zero or not.
Here, it is till 100. And the logic is such that the divisor will be less than or equal to dividend(b <= a/b).
SO a%b == 0 means that if a is divided by b and if remainder is zero, then it is a prime 'cause prime numbers have no factors rather than 1 and the number itself.
Hope you're clear about this.
SO keep calm, code and HIT A UPVOTE OR COMMENT IF SOMETHING IS WRONG!
I have a method getNextPrime(int num) which is supposed to identify the closest prime number after the value received by the method.
If num is even, it will increment it and call itself again. If it is odd, it will run a for loop to check if it is divisible by odd numbers between 3 and num's half value. If it is then it will increase num by 2 and the method will call itself again, otherwise it will return the new num value which is a prime number.
The problem is, when the program gets to the return statement, it will jump to the if statement and return the original value of num + 1. I have been debugging this for a while and it just doesn't make sense. Wherever I place the return statement, the method just jumps to the if statement instead of terminating the method and returning the value to where it is being called from.
public int getNextPrime(int num){
if(num % 2 == 0){
//even numbers are not prime
getNextPrime(++num);
}
else{
for(int i = 3; i < (num + 1) / 2; i += 2){
if(num % i == 0) {
getNextPrime(num += 2); //consider odd numbers only
}
}
}
return num; //jumps to if and terminates
}
However, if I change the else statement to a separate if statement, if(num % 2 != 0) it works.
Why does this happen?
*Note - the values given to the method are greater than 3, the fact that 1, 2, and 3 are primes doesn't matter.
There is only one structural problem here. Reaching a single return does not collapse the entire call stack, it only returns to the previous invocation.
You need to save the result of calling getNextPrime() every time and use that as the return value, so the value actually found gets passed back along the call chain and returned to the initial caller. As it stands you return only the number that was passed in since you never modify it.
The fix is a very simple modification. Where you have
getNextPrime(++num);
... and ...
getNextPrime(num+2);
replace them with
return getNextPrime(++num);
... and ...
return getNextPrime(num+2);
The problem with the algorithm you chose is that it is inefficient. You need to test divisibility using smaller primes only, not all odd numbers, and only up to the square root of the original number.
Implementation is left as an exercise.
Lets try to look at the call stack when we call your function with argument 8;
The first call is : getNextPrime(8). As the number is even, the function goes into the if part and calls itself again with getNextPrime(9). This time the else part kicks in, checks for divisibility in for loop, finds that 9 is divisible so calls the getNextPrime(11). Now getNextPrime(11) goes again the else and the for loop and finds that 11 was prime and returns the number 11 to the caller, but if you look closely, you don't store this value in a variable, the num variable in the getNextPrime call was 9, and when getNextPrime(9) returns it returns that value to getNextPrime(8). In your getNextPrime(8) too you haven't really stored the num variable returned from the recursion call stack. You are just return the num variable defined in that function, which you happened to increment before calling the getNextPrime(11) so this value is 9, and 9 is returned.
Corrected program with the same if else block is given below for your reference.
public static int genNextPrime(int num) {
if (num % 2 == 0) {
num = genNextPrime(++num);
} else {
for (int i = 3; i < (num + 1) / 2; i += 2) {
if (num % i == 0) {
num += 2;
num = genNextPrime(num);
}
}
}
return num;
}
Your return statement works fine but ..you have left 1,2 and 3 out of your logic. 2 is a even prime number and 1 is not a prime number.
This Java code prints out prime numbers between 2-100.
And this works fine.
This code is not done by me.
But I am trying to figure out what is happening with this code.
Can anyone tell me what is happening after the second (for) loop?
class primenumbers{
public static void main(String args[])
{
int i, j;
boolean isprime;
for(i=2; i < 100; i++) {
isprime = true;
// see if the number is evenly divisible
for(j=2; j <= i/j; j++)
// if it is, then its not prime
if((i%j) == 0) isprime = false;
if(isprime)
System.out.println(i + " is prime.");
}
}
}
The first loop just for generating numbers from 2 to 100.
The second loop tries to find if the number is divisible by any other number. Here we try to divide a the number with a set of numbers (2 to prime_index).
Let's say the number is 10, the prime index is 10/2 = 5 for first iteration(j = 2). Which means, if the number 10 is not divisible by any number between 2 and 5, it's a prime number. It's divisible by 2 itself making it a non prime number.
Let's say the number is 9, now the prime index is 9/2 = 4 for first iteration(j = 2). Now, 9 % 2 gives 1 as reminder. So, loop continues for second iteration (j = 3). Now the prime index is 9/3 = 3 (Note here the prime index value is reduced from 4 to 3) So, now if the number is not divisible by 3, its decided as a prime number.
So, for every iteration, the prime index will reduce, making the number of iterations reduced.
Example for Number 97,
j = 2, prime index = 97/2 = 48 (no of iterations for loop)
j = 3, prime index = 97/3 = 32 (no of iterations for loop)
j = 4, prime index = 97/4 = 24 (no of iterations for loop)
j = 5, prime index = 97/5 = 19 (no of iterations for loop)
j = 6, prime index = 97/6 = 16 (no of iterations for loop)
j = 7, prime index = 97/7 = 13 (no of iterations for loop)
j = 8, prime index = 97/8 = 12 (no of iterations for loop)
j = 9, prime index = 97/9 = 10 (no of iterations for loop)
j = 10, prime index = 97/10 = 9 (loop exits as condition failed 10 <= 9 and declares 97 as a prime number)
Now, here the loop actually took 10 iterations instead of the proposed 48 iterations.
Let's modify the code for better understanding.
public static void main(String args[]) {
// Number from 2 to 100
for(int i=2; i < 100; i++) {
if (isPrimeNumber(i)) {
System.out.println(i + " is prime");
}
}
}
Now, lets see a method isPrimeNumberNotOptimized() which is not optimized.
private static boolean isPrimeNumberNotOptimized(int i) {
for(int j=2; j <= i/2; j++) {
// if it is, then its not prime
if((i%j) == 0) {
return false;
}
}
return true;
}
And, another method isPrimeNumberOptimized() which is optimized with prime index.
private static boolean isPrimeNumberOptimized(int i) {
for(int j=2; j <= i/j; j++) {
// if it is, then its not prime
if((i%j) == 0) {
return false;
}
}
return true;
}
Now, both methods will run and print the prime numbers correctly.
But, the optimized method will decide 97 is a prime number at 10th iteration.
And, the non-optimized method will decide the same in 48th iteration.
Hope, you understand it now.
FYI: prime index is the number we used for calculation. Such that if a number is not divisible between 2 & the derived prime index, its a prime number
This is a modification of the Sieve of Eratosthenes.
First, I'll just summarize what the sieve of Eratosthenes does, you can skip to the last paragraph if you already know this. The sieve of Eratosthenes algorithm loops through a certain boundary of numbers. (Say 2 - 100). For every number it loops through, it cancels out multiples, for example, since 2 is a prime number (true), all multiples of 2 are not (They are false). Same for 3, 5, and so on; and the algorithm skips every predetermined non-prime number. Therefore, a simulation of the algorithm would be:
2 ---prime number... cancels out 4, 6, 8, 10, 12....
3 ---prime number... cancels out 6, 9, 12, 15, 18...
4 --- ALREADY CANCELLED OUT... Skip
5 --- prime number... cancels out 10, 15, 20, 25...
6 --- ALREADY CANCELLED OUT... Skip
The numbers not cancelled are therefore the prime numbers. You can also read this for more information: http://www.geeksforgeeks.org/sieve-of-eratosthenes/
Now, to your question, your algorithm loops through the list of numbers. For each number(say x), it checks if any of the previous numbers looped through (i / j) is a factor of the x. The reason why i/j is used as the boundary for the second for loop is for efficiency. If you're checking if 10 (for example) is a prime number, there's no need to check whether 6 is a factor. You can conveniently stop at n/(n/2). That's what that part is trying to achieve.
Outer (first) loop enumerates all numbers in [2,100).
Inner (second) loop checks if a current number from the first loop is dividable by anything.
This check is done using % (remainder): (i%j)==0 when remainder of division i by j is 0. By definition when remainder is zero i is dividable by j and therefore is not a prime : isprime=false.
You only need to check in [2,i/j] because you only need to check up to sqrt(i) (explanation in the last section).
Having said that the inner loop can be re-written as:
...
int s = sqrt(i);
for(j=2; j <= s; j++)
...
however sqrt is more expensive than division, therefore it's better to rewrite j<=sqrt(i) as (squaring both sides) j^2 < i and j*j<i and j<i/j. When j is big enough j*j might overflow therefore both sides were divided by j in the final step.
Explanation of sqrt(i) taken from here: Why do we check up to the square root of a prime number to determine if it is prime?
if i is not prime, then some x exists so that i = x * j. If both x and j are greater than sqrt(i) then x*j would be greater than i.
Therefore at least one of those factors (x or j) must be less than or equal to the square root of i, and to check if i is prime, we only need to test for factors less than or equal to the square root.
public class PrimeNumber {
//check prime number
public static boolean prime(int number){
boolean isPrime=true;
for(int i=number-1;i>1;i--){
if(number%i==0){
isPrime=false;
System.out.println(i);
break;
}
}
return isPrime;
}
public static boolean getPrimeUsingWhile(int number){
boolean isPrime=true;
Integer temp=number-1;
while (temp>1){
if(number%temp==0){
isPrime=false;
break;
}
temp--;
}
return isPrime;
}
//print primenumber given length
public static List<Integer> prinPrimeList(){
boolean isPrime=true;
List<Integer> list=new ArrayList<>();
int temp=2;
while (list.size()<10){
for(int i=2;i<temp;i++){
if(temp%i==0){
isPrime=false;
break;
}else{
isPrime=true;
}
}
if(isPrime){list.add(temp);}
temp++;
}
return list;
}
public static void main(String arg[]){
System.out.println(prime(3));
System.out.println(getPrimeUsingWhile(5));
System.out.println(Arrays.toString(prinPrimeList().toArray()));
}
}
*disclaimer, when I say "I have verified this is the correct result", please interpret this as I have checked my solution against the answer according to WolframAlpha, which I consider to be pretty darn accurate.
*goal, to find the sum of all the prime numbers less than or equal to 2,000,000 (two million)
*issue, my code will output the correct result whenever my range of tested values is approximately less than or equal to
I do not output correct result once test input becomes larger than approximately 1,300,000; my output will be off...
test input: ----199,999
test output: ---1,709,600,813
correct result: 1,709,600,813
test input: ----799,999
test output: ---24,465,663,438
correct result: 24,465,663,438
test input: ----1,249,999
test output: ---57,759,511,224
correct result: 57,759,511,224
test input: ----1,499,999
test output:--- 82,075,943,263
correct result: 82,074,443,256
test input: ----1,999,999
test output:--- 142,915,828,925
correct result: 142,913,828,925
test input: ----49,999,999
test output:--- 72,619,598,630,294
correct result: 72,619,548,630,277
*my code, what's going on, why does it work for smaller inputs? I even used long, rather than int...
long n = 3;
long i = 2;
long prime = 0;
long sum = 0;
while (n <= 1999999) {
while (i <= Math.sqrt(n)) { // since a number can only be divisible by all
// numbers
// less than or equal to its square roots, we only
// check from i up through n's square root!
if (n % i != 0) { // saves computation time
i += 2; // if there's a remainder, increment i and check again
} else {
i = 3; // i doesn't need to go back to 2, because n+=2 means we'll
// only ever be checking odd numbers
n += 2; // makes it so we only check odd numbers
}
} // if there's not a remainder before i = n (meaning all numbers from 0
// to n were relatively prime) then move on
prime = n; // set the current prime to what that number n was
sum = sum + prime;
i = 3; // re-initialize i to 3
n += 2; // increment n by 2 so that we can check the next odd number
}
System.out.println(sum+2); // adding 2 because we skip it at beginning
help please :)
The problem is that you don't properly check whether the latest prime to be added to the sum is less than the limit. You have two nested loops, but you only check the limit on the outer loop:
while (n <= 1999999) {
But you don't check in the inner loop:
while (i <= Math.sqrt(n)) {
Yet you repeatedly advance to the next candidate prime (n += 2;) inside that loop. This allows the candidate prime to exceed the limit, since the limit is only checked for the very first candidate prime in each iteration of the outer loop and not for any subsequent candidate primes visited by the inner loop.
To take an example, in the case with the limit value of 1,999,999, this lets in the next prime after 1,999,999, which is 2,000,003. You'll note that the correct value, 142,913,828,922, is exactly 2,000,003 less than your result of 142,915,828,925.
A simpler structure
Here's one way the code could be structured, using a label and continue with that label to simplify structure:
public static final long primeSum(final long maximum) {
if (maximum < 2L) return 0L;
long sum = 2L;
// Put a label here so that we can skip to the next outer loop iteration.
outerloop:
for (long possPrime = 3L; possPrime <= maximum; possPrime += 2L) {
for (long possDivisor = 3L; possDivisor*possDivisor <= possPrime; possDivisor += 2L) {
// If we find a divisor, continue with the next outer loop iteration.
if (possPrime % possDivisor == 0L) continue outerloop;
}
// This possible prime passed all tests, so it's an actual prime.
sum += possPrime;
}
return sum;
}
I'm working on a prime factorization program in Java one that displays all prime factors of a number even if they are repeated. And I have this:
public static void factors(int a)
{
int c=1;
for(int i = 1; i <= a;i++)
{
if(a%i == 0)
{
for(int k = 2; k < i; k++)
{
if(i%k == 0)
{
c = 1;
break;
}
else
{
c = 0;
}
}
if(c == 0 || i == 2)
{
System.out.print(i+ ", ");
}
}
}
}
I need to account for repeated factors (as in 2, 2, 2 for 8). How could I do that without completely restructuring?
I think you should start over, and build an algorithm from this simple description:
Prepare a List<Integer> of prime numbers that are less than or equal to 2^16
Run through this list from low to high, trying each prime in turn as a candidate divisor
Every time you run into a working divisor, continually divide it out until you can no longer divide the number by it; then continue to the next prime
Once you reach the end of the list of primes, your remaining number should be printed as well, unless it is equal to 1.
Finding a list of primes is a fun problem in itself. Dijkstra wrote a fascinating chapter on it back in 1972. This article has a C++ implementation and a very nice discussion.
You can have another collection that maintains the factors and their count and can finally account for repeated factors. A map with counts would be my choice.
(1) if(c == 0 || i == 2) is wrong, it will print 2 for a == 5 as well.
(2) In order to do what you are asking without changing the code (*) - you should count how many times each prime factor is diviseable by the number. It can be done by simply adding a new loop before your print statement [pseudo code]:
boolean b = true;
int k = 1;
while (b) {
if (a % (int) Math.pow(i, k+1) == 0) k++;
else b = false;
}
at the end of this loop, k denotes how many times i is a prime factor of a.
(*) Note: Though this approach should work, I'd still go with #KerrekSB suggestion to a redesign.