How to find prime factorization of number using loop? - java

I'm supposed to find the prime factorization of this number: 600851475.
Prime factorization, according to my teacher and this website, http://www.mathsisfun.com/prime-factorization.html, are prime numbers that multiplied give you that number. So for example 12, even though its factors are 2,3,4,6, the prime factors WON'T be just 2 & 3, but 2,2,3.
I have the algorithm to find a prime factor allready, but I can't find a way to loop so that it keeps finding the rest until there are no more prime factors.
This is what i got:
public class primeFactors {
public static void main(String[] args) {
int d= 600851475;
int i = 2;
if (d%i!=0) {i++;}
if (d%i==0) {d=d/i;}
System.out.println(i);
}
}
and it prints this: 3.
If i copy paste it multiple times it does print different things:
public class primeFactors {
public static void main(String[] args) {
int d= 600851475;
int i = 2;
if (d%i!=0) {i++;}
if (d%i==0) {d=d/i;}
System.out.println(i);
if (d%i!=0) {i++;}
if (d%i==0) {d=d/i;}
System.out.println(i);
if (d%i!=0) {i++;}
if (d%i==0) {d=d/i;}
System.out.println(i);
if (d%i!=0) {i++;}
if (d%i==0) {d=d/i;}
System.out.println(i);
}
}
That one prints: 3, 3, 4, 5, 5.
How can I do this with loops? I tried with do while loops( do { if section} while (d>i) {print i} ), but it doesn't work. I also tried with for loop (i=2;i<=d;i++) & it doesn't work. It gives me composite numbers too.
HELP PLEASE!!

Since this is an assignment, the most I'll give you is a general direction: the easiest way to write this will be to try candidate divisors and reduce. For example:
130 - try 2, it divides, so reduce
65 - maybe there's another 2 in there? try 2 again. It doesn't divide, so move on
65 - try 3 - no. 4? no. 5? yes, it divides, so reduce.
13 - Is there another 5 in there? no. try 6, 7, 8, 9, 10, 11, 12. Okay, you're done.
So you need to try candidate divisors in a loop, and you need an inner loop to make sure you cast out any repeated factors (for example, 525 will have the prime factors 3, 5, and 7 but you still want to get rid of that second 5). That should get you on the right track.
Clearly, there will be more efficient ways to write this, but if you're stuck, start with the simplest possible thing that could work, and get that working.

You only need something like this (Perhaps this is not the most efficient way but it was pretty straight forward and easier to understand) :
int d= 600851475;
for (int i = 2 ; i < (d / 2) ; i++){
if(isPrime(i)){
if(d % i ==0){
System.out.println(i + "Is a prime factor of " + d);
}
}
}
But first you will need to have this method that check if it is a prime number or not
public static boolean isPrime(int n){
for(int i = 2 ; i < n ; i++){
if(n % i == 0){
return false;
}
}
return true;
}

Try to use a for loop.
for (int i = 2; i <= d; i++)
{
//implement if statement here
}
This should point you in the right direction.

You have the right idea. You need to divide each factor until it no longer divides.
// this will print all prime divisors for n
for (int i = 2; n != 1; i++)
{
while (n % i == 0)
{
System.out.println (i);
n /= i;
}
}

How to find the prime factorization of a number?
Here is what I tried:
def p_factorization(n):
#Finding the factors of n.
num=[i for i in range(1,n+1) if n%i==0]
#Finding the prime factors of n.
#Now prime_num checks to see if any of the factors of 36 have more than two "subfactors".
prime_num=[i for i in range(2,max(num)) if len([j for j in range(1,i+1) if i%j==0])<=2 and max(num)%i==0]
return prime_num
#Explanation:
#The num list is self-explanatory. It finds all of the factors of the number n.
#The prime_num list comprehension is where it gets complicated:
#The i represents all of the numbers in the range of the original factors that we found,
#then we know that a number is prime if it has two or fewer factors, hence the if condition
#applying to the len of the factors of i, which is being iterated through.
#For example, 4 is not a prime number because the length of the list of factors is
#3 [1,2,4].
And of course, we still need max(num) to be divisible by i.
You are very welcome!

Related

Program isn't terminating for a specific input

I am trying to write a program that will let me know if a number has the odd divisor greater than one. Let's n be the number, and x be the divisor. x%2!=0 and x>1;
Code:
import java.util.Scanner;
public class Simple1{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
long n;
for(int i=0; i<t; i++) {
n=sc.nextLong();
if(n<3)System.out.println("NO");
else {
if(n%2!=0)System.out.println("YES");
else {
int ans=0;
for(long j=3; j<=n/2; j+=2) {
if(n%j==0) {
ans=1;
break;
}
}
if(ans==1)System.out.println("YES");
else System.out.println("NO");
}
}
}
}
}
This java code works fine. But it's not working for a specific input.. and that is n = 1099511627776. If I change the last digit to any int other than 6, then it works fine and gives output. Even numbers greater than that works. But only this number n=1099511627776, when I input this to my program, no terminating happens and no output. Help me to figure out what happens here.
The number 1099511627776 is two to the power 40. That means it has to check through the whole big for-loop to find no odd factors. You would get the same problem, to different extents, with 2199023255552 (2 to the 41) and 549755813888 (2 to the 39). You have to wait longer if you want to do it this way.
A much faster way is to divide n by 2 until you get an odd number.
E.g.
long n = sc.nextLong();
while (n > 1 && n % 2 == 0) {
n /= 2;
}
if (n > 1) {
System.out.println("Yes.");
} else {
System.out.println("No.");
}
An even faster way to tell if a number is a power of two is a bit-twiddling hack:
// Powers of 2 have the property that n & (n-1) is zero
if ((n & (n - 1)) != 0) {
System.out.println("Yes."); // Not a power of two, so has an odd factor
} else {
System.out.println("No."); // Is a power of two, so does not have an odd factor
}
Can you get rid of the powers of two another way?
long number = 1099511627776l;
long r = number >> Long.numberOfTrailingZeros​(number);
Then r is an odd divisor, which might be greater than one.
If you think in base 10, then you know a number is divisible by ten if has a trailing zero. You can remove all of the powers of 10 by removing all of the zeros. It is the same for base 2, you can remove all of the factors of 2 by removing all of the trailing zeros (in binary representation).

ProjectEuler's distinct prime factors of a given number

folks, I've been struggling to figure out the algorithm to get the list of all of the prime factors of the given number (in my case, the given number is myNumber = 14). For example,
14 = 2 × 7
15 = 3 × 5
645 = 3 × 5 × 43
646 = 2 × 17 × 19
But my code is running infinitely and I'm not pretty sure if my algorithm works fine. Could smb take a look or give me a hand how to see the problem? Thanks in advance!
import java.util.*;
public class DistinctFactors {
public static final List<Integer> myList = new ArrayList<>();
public static void main(String[] args){
int result = 1;
int myNumber = 14;
int i = 2;
while(result != myNumber){
if(isPrime(i)){
myList.add(i);
result *= i;
}
i++;
}
for(int j = 0; i < myList.size(); j++){
System.out.print(myList.get(j) + " ");
}
}
private static boolean isPrime(int number){
for(int i = 2; i < number; i++){
if(number % 2 == 0){
return false;
}
}
return true;
}
}
I mean, let's look at what the values of result and i will be.
Pass 1: r = 1, i = 2
Pass 2: r = 2, i = 3
Pass 3: r = 6, i = 4
Pass 4: r = 6, i = 5
Pass 5: r = 30, i = 6
From this point on, r will only increase, and it's already greater than 14. So of course this loop will never terminate.
Your method is also extremely wrong. I have no idea why you chose this way to try and get prime factors.
Not to mention, even your isPrime method is kind of dumb. It checks all the way up to the number you're checking, which is extremely wasteful.
To check if a number n is prime, you should instead compute the square root; if it is an integer, then the number is obviously not prime. Otherwise, take the floor of that sqrt(n) - let's call it k - and run the loop up to k. If n is not prime, you will find a divisor in that range; if you find none, n is prime.
(That is an O(log(n)) method. The best method is the one that involves checking whether the number satisfies Fermat's Little Theorem for random values, which is constant time).
EDIT: Well, not exactly constant time if you don't consider certain operations O(1). For huge numbers it's much better than the other method
Your current loop just checks whether the number is even a bunch of times...

Prime Numbers in Java - Algorithms

I have started learning to code in Java and decided I would use the Project Euler site to give me little tasks to try and complete with each bit of new coding I learn. So I came across Problem 3:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
I thought about the problem and researched many different theories about prime numbers and how they can be found via various different calculations (Sieve of Eratosthenes being an example) and the solution I conjured up was to test numbers from 2 --> n and see if they were a prime number, if they were then I would divide the Tn variable (in this case 600851475143) by the newly discovered prime number and see if it was a factor. If it was, I would assign it to the variable Hp (Highest Prime number) and at the end of the program I would output Hp to the console to give my result.
Here is my code:
public class Largest_Prime_Factor_NEW_SOLUTION {
static long Tn = 600851475143L;
static long Hp = 0;
static boolean isPrime = false;
public static void main(String[] args) {
for (long i=2; i<Tn; i++) {
System.out.println("TESTING NUMBER " + i);
for (long k=2; k < i; k++) {
if (i % k == 0) {
System.out.println(i + " IS NOT A PRIME");
break;
} else if (k + 1 == i) {
isPrime = true;
}
}
if (isPrime) {
System.out.println(i + " IS A PRIME");
if (Tn % i == 0) {
System.out.println(Tn + " IS DIVISIBLE BY " + i);
Hp = i;
} else {
System.out.println(Tn + " IS NOT DIVISIBLE BY " + i);
}
}
isPrime = false;
}
System.out.println("THE HIGHEST PRIME NUMBER OF " + Tn + " IS " + Hp);
}
}
Now I know that this code is very inefficient and for just starting I have managed to condense it from where I began (there were loops everywhere!) but what I am is asking is, how can I improve this? It's eating away at me because everything I research contradicts what others would do and it's very confusing. I have tried the sieve method but i understand that a boolean array can only be an int array and never a long array?
I understand that when beginning to code I will be limited to what knowledge I can use, but just out of interest, I am keen to see what the final solution would be.
What you can do is find the lowest divisor of Tn. Suppose that is p, find the lowest divisor again for Tn/p and so on.
Now, at every step p is prime[explanation below]. So collect them and they are the prime divisors of Tn.
For better time-complexity, you can check for divisors up to upto ceil(sqrt(Tn)) only, instead of Tn-1.
And when you start checking for prime divisor for Tn, you can start with 2. And once you get a prime divisor p don't start again from 2 for Tn/p. Because, Tn/p is also a divisor of Tn and since Tn does not have divisors less than p, Tn/p does not have it too. So start with p again[p can have multiple power in Tn]. If p does not divide Tn, move to p+1.
Example :
Tn = 45
1. start with 2. 2 does not divides 45.
2. next test is for 3. 45 is divisible by 3. So 3 is a prime divisor of it.
3. Now check prime divisors from 45/3 = 15, but start with 3. not from 2 again.
4. Well, 15 is divisible by 3. So start with 15/3 = 5
5. Note for 5, ceil(sqrt(5)) is 3. But 5 is not divisible by 3. But since 4 > ceil(sqrt(5))
and we can say 5 is a prime without any doubt.
So the prime divisor of 45 are 3 and 5.
Why smallest divisor(except 1) of a number is a prime ?
Suppose above statement is false. Then a number N has a smallest yet composite divisor, say C.
So C|N
Now C is composite so, it has divisor less than itself but greater than one.
Say such a divisor of C is P.
So P|C , but we have C|N => P|N where 1 < P < C.
This contradicts our assumption that C is the smallest divisor of N, so smallest divisors of a number is always a prime.
Thank you for all your help, after reading through the comments and answers I managed to condense the code much further to the following:
public class Largest_Prime_Factor_NEW_SOLUTION_2 {
static long Tn = 600851475143L;
public static void main(String[] args) {
for (long i = 2; i < Math.sqrt(Tn); i++) {
if(Tn % i == 0) {
Tn = Tn / i;
i--;
}
}
System.out.println(Tn);
}
}
and it works perfect! Thanks again for your help and time to help me understand. I understand it was more a mathematical problem than a coding problem, but it helped me understand a few things. I'm now off to learn something else :)
Since you are doing this as a learning exercise, when you have improved you current program enough, why not try solving the same problem in a different way? The Fermat Factorization Method finds large factors first.
There are many ways to improve a program like this, but the improvements have to do mostly with mathematics and not programming:
When looking for factors, check each number, not just primes. If you find a factor check if it's prime. You'll save yourself of many primality checks this way.
The greatest prime factor of a composite number can be at most the number's square root, so you can stop the iteration earlier.
Use a fast primality test instead of doing trial divisions http://en.wikipedia.org/wiki/Primality_test
Then again, this is a one-off. Don't overcomplicate it.
A simple algorithm for factoring a composite number by trial division goes like this:
function factors(n)
f, fs := 2, []
while f * f <= n
while n % f == 0
fs.append(f)
n := n / f
f := f + 1
if n > 1
fs.append(n)
return fs
That algorithm can be improved, and there are better algorithms for factoring large numbers, but it's sufficient for your task. When you are ready for more, I modestly recommend the essay Programming with Prime Numbers at my blog, which includes implementations of that algorithm and others in Java.
This is java version of this:
static boolean isPrime(int n){
if (n == 2) return true;
if (n == 3) return true;
if (n % 2 == 0) return false;
if (n % 3 == 0) return false;
int i = 5;
int w = 2;
while (i * i <= n) {
if(n % i == 0)
return false;
i += w;
w = 6 - w;
}
return true;
}
As it is described by #Alexandru: It's a variant of the classic O(sqrt(N)) algorithm. It uses the fact that a prime (except 2 and 3) is of form 6k-1 and 6k+1 and looks only at divisors of this form.

Why is my solution to project euler 1 not working?

I decided to just try and get the small example of only going to 10 like the example shown.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 >and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
public class project1 {
public static void main(String[] args) {
int three=0;
int tot3=0;
int five=0;
int tot5=0;
int total;
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
while (tot5<10) {
five+=5;
tot5=tot5+five;
};
total=tot3+tot5;
System.out.println("Three's: " + tot3);
System.out.println("Five's: " + tot5);
System.out.println("Combined: " + total);
}
}
My output is as show:
Three's: 18
Five's: 15
Combined: 33
Numbers that are both multiples of 3 and 5 (like 15 for instance), are counted twice - once in each loop.
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
I think you mean
while (tot3<10) {
three += tot3; // Add this multiple of 3 to the total.
tot3+=3; // increment the "next multiple"
}
(same for 5)
Lone nebula also makes a good point - you'd need to add logic to the "5" loop to check it's not already counted in the 3 loop. The mod (%) operator can help there.
First,
while (tot3<10) {
three+=3;
tot3=tot3+three;
};
while (tot5<10) {
five+=5;
tot5=tot5+five;
};
This should be
while (three<10) {
three+=3;
tot3=tot3+three;
};
while (five<10) {
five+=5;
tot5=tot5+five;
};
Because you're concerned about when you start counting numbers above 10, not when your TOTAL of those numbers is above 10.
Secondly, your solution will count numbers that are a multiple of three and of five twice. For example, 15 will be added twice. Learn about the modulo operator, %, to come up with a solution to this (for example, not adding five to the tot5 count if five % 3 == 0)
I would recommend looking into using the modular operator to solve this problem. In java % will allow you to perform modular arithmetic. For example any multiple of 3 such as 9 % 3 = 0 while 9 % 2 = 1. It can be thought of as what remains after you divide the first number by the second. All multiples of a number modded by that number will return zero.
Keep track of your variables through the loop and you'll see the problem:
for tot3
=3
=9
=18
=30
You're keeping track of the sum, instead of tracking the multiples. This problem is partially solved in by
while(three<10)
Again, keeping track of the variable through the loop you'll see that this is wrong- it stops at 12, not 9 as you want it. Change it to
While(three<9)
//ie the last divisible number before the limit, or that limit if its divisible (in the case of 5)
All said, an infinitely more elegant solution would involve modulus and a nice little if statement. I hope this helps!
public class project1 {
public static void main(String[] args) {
int number = 0;
int total = 0;
while (number < 10) {
System.out.println(number);
if ((number % 3) == 0) {
System.out.println(number + " is a multiple of 3");
total = total + number;
}
else if ((number % 5) == 0) {
System.out.println(number + " is a multiple of 5");
total = total+number;
}
number++;
}
System.out.println("total = "+ total);
}
}
Looking at how slow I was, I did roughly the same thing as everyone else but swapped to a modulus function. The modulus function gives you the remainder(int) of dividing the first number by the second number, and can be compared to another integer. Here I have used it to check if the current number is directly divisible by 3 or 5, and add it to the total if the value is true.
Try this
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong()-1;
System.out.println((n-n%3)*(n/3+1)/2 + (n-n%5)*(n/5+1)/2 - (n-n%15)*(n/15+1)/2);
}
}
}

Calculating and printing the nth prime number

I am trying to calculate prime numbers, which I've already done. But I want to calculate and print ONLY the nth prime number (User input), while calculating the rest (They won't be printed) only the nth prime number will be printed.
Here's what I've written so far:
import java.util.Scanner;
/**
* Calculates the nth prime number
* #author {Zyst}
*/
public class Prime {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n,
i = 2,
x = 2;
System.out.printf("This program calculates the nth Prime number\n");
System.out.printf("Please enter the nth prime number you want to find: ");
n = input.nextInt();
for(i = 2, x = 2; i <= n; i++) {
for(x = 2; x < i; x++) {
if(i % x == 0) {
break;
}
}
if(x == i) {
System.out.printf("\n%d is prime", x);
}
}
}
}
This is the program I wrote to calculate the prime numbers from 1 to n. However, I want it to only print the nth prime number,
What I've thought of doing is making some sort of count int and ++ing it every time it finds a prime, and when the count == n then it prints out that number, but I can't quite figure out how to land it.
To calculate the n-th prime, I know two main variants.
The straightforward way
That is to count all the primes starting from 2 as you find them until you have reached the desired nth.
This can be done with different levels of sophistication and efficiency, and there are two conceptually different ways to do it. The first is
Testing the primality of all numbers in sequence
This would be accomplished by a driver function like
public static int nthPrime(int n) {
int candidate, count;
for(candidate = 2, count = 0; count < n; ++candidate) {
if (isPrime(candidate)) {
++count;
}
}
// The candidate has been incremented once after the count reached n
return candidate-1;
}
and the interesting part that determines the efficiency is the isPrime function.
The obvious way for a primality check, given the definition of a prime as a number greater than 1 that is divisible only by 1 and by itself that we learned in school¹, is
Trial division
The direct translation of the definition into code is
private static boolean isPrime(int n) {
for(int i = 2; i < n; ++i) {
if (n % i == 0) {
// We are naive, but not stupid, if
// the number has a divisor other
// than 1 or itself, we return immediately.
return false;
}
}
return true;
}
but, as you will soon discover if you try it, its simplicity is accompanied by slowness.
With that primality test, you can find the 1000th prime, 7919, in a few milliseconds (about 20 on my computer), but finding the 10000th prime, 104729, takes seconds (~2.4s), the 100000th prime,1299709, several minutes (about 5), the millionth prime, 15485863, would take about eight and a half hours, the ten-millionth prime, 179424673, weeks, and so on. The runtime complexity is worse than quadratic - Θ(n² * log n).
So we'd like to speed the primality test up somewhat. A step that many people take is the realisation that a divisor of n (other than n itself) can be at most n/2.
If we use that fact and let the trial division loop only run to n/2 instead of n-1, how does the running time of the algorithm change?
For composite numbers, the lower loop limit doesn't change anything. For primes, the number of trial divisions is halved, so overall, the running time should be reduced by a factor somewhat smaller than 2. If you try it out, you will find that the running time is almost exactly halved, so almost all the time is spent verifying the primality of primes despite there being many more composites than primes.
Now, that didn't help much if we want to find the one-hundred-millionth prime, so we have to do better. Trying to reduce the loop limit further, let us see for what numbers the upper bound of n/2 is actually needed. If n/2 is a divisor of n, then n/2 is an integer, in other words, n is divisible by 2. But then the loop doesn't go past 2, so it never (except for n = 4) reaches n/2. Jolly good, so what's the next largest possible divisor of n?
Why, n/3 of course. But n/3 can only be a divisor of n if it is an integer, in other words, if n is divisible by 3. Then the loop will exit at 3 (or before, at 2) and never reach n/3 (except for n = 9). The next largest possible divisor ...
Hang on a minute! We have 2 <-> n/2 and 3 <-> n/3. The divisors of n come in pairs.
If we consider the pair (d, n/d) of corresponding divisors of n, either d = n/d, i.e. d = √n, or one of them, say d, is smaller than the other. But then d*d < d*(n/d) = n and d < √n. Each pair of corresponding divisors of n contains (at least) one which does not exceed √n.
If n is composite, its smallest nontrivial divisor does not exceed √n.
So we can reduce the loop limit to √n, and that reduces the runtime complexity of the algorithm. It should now be Θ(n1.5 * √(log n)), but empirically it seems to scale a little bit better - however, there's not enough data to draw reliable conclusions from empirical results.
That finds the millionth prime in about 16 seconds, the ten-millionth in just under nine minutes, and it would find the one-hundred-millionth in about four and a half hours. That's still slow, but a far cry from the ten years or so it would take the naive trial division.
Since there are squares of primes and products of two close primes, like 323 = 17*19, we cannot reduce the limit for the trial division loop below √n. Therefore, while staying with trial division, we must look for other ways to improve the algorithm now.
One easily seen thing is that no prime other than 2 is even, so we need only check odd numbers after we have taken care of 2. That doesn't make much of a difference, though, since the even numbers are the cheapest to find composite - and the bulk of time is still spent verifying the primality of primes. However, if we look at the even numbers as candidate divisors, we see that if n is divisible by an even number, n itself must be even, so (excepting 2) it will have been recognised as composite before division by any even number greater than 2 is attempted. So all divisions by even numbers greater than 2 that occur in the algorithm must necessarily leave a nonzero remainder. We can thus omit these divisions and check for divisibility only by 2 and the odd numbers from 3 to √n. This halves (not quite exactly) the number of divisions required to determine a number as prime or composite and therefore the running time. That's a good start, but can we do better?
Another large family of numbers is the multiples of 3. Every third division we perform is by a multiple of 3, but if n is divisible by one of them, it is also divisible by 3, and hence no division by 9, 15, 21, ... that we perform in our algorithm will ever leave a remainder of 0.
So, how can we skip these divisions? Well, the numbers divisible by neither 2 nor 3 are precisely the numbers of the form 6*k ± 1. Starting from 5 (since we're only interested in numbers greater than 1), they are 5, 7, 11, 13, 17, 19, ..., the step from one to the next alternates between 2 and 4, which is easy enough, so we can use
private static boolean isPrime(int n) {
if (n % 2 == 0) return n == 2;
if (n % 3 == 0) return n == 3;
int step = 4, m = (int)Math.sqrt(n) + 1;
for(int i = 5; i < m; step = 6-step, i += step) {
if (n % i == 0) {
return false;
}
}
return true;
}
This gives us another speedup by a factor of (nearly) 1.5, so we'd need about one and a half hours to the hundred-millionth prime.
If we continue this route, the next step is the elimination of multiples of 5. The numbers coprime to 2, 3 and 5 are the numbers of the form
30*k + 1, 30*k + 7, 30*k + 11, 30*k + 13, 30*k + 17, 30*k + 19, 30*k + 23, 30*k + 29
so we'd need only divide by eight out of every thirty numbers (plus the three smallest primes). The steps from one to the next, starting from 7, cycle through 4, 2, 4, 2, 4, 6, 2, 6. That's still easy enough to implement and yields another speedup by a factor of 1.25 (minus a bit for more complicated code). Going further, the multiples of 7 would be eliminated, leaving 48 out of every 210 numbers to divide by, then 11 (480/2310), 13 (5760/30030) and so on. Each prime p whose multiples are eliminated yields a speedup of (almost) p/(p-1), so the return decreases while the cost (code complexity, space for the lookup table for the steps) increases with each prime.
In general, one would stop soonish, after eliminating the multiples of maybe six or seven primes (or even fewer). Here, however, we can follow through to the very end, when the multiples of all primes have been eliminated and only the primes are left as candidate divisors. Since we are finding all primes in order, each prime is found before it is needed as a candidate divisor and can then be stored for future use. This reduces the algorithmic complexity to - if I haven't miscalculated - O(n1.5 / √(log n)). At the cost of space usage for storing the primes.
With trial division, that is as good as it gets, you have to try and divide by all primes to √n or the first dividing n to determine the primality of n. That finds the hundred-millionth prime in about half an hour here.
So how about
Fast primality tests
Primes have other number-theoretic properties than the absence of nontrivial divisors which composite numbers usually don't have. Such properties, if they are fast to check, can form the basis of probabilistic or deterministic primality tests. The archetypical such property is associated with the name of Pierre de Fermat, who, in the early 17th century, found that
If p is a prime, then p is a divisor of (ap-a) for all a.
This - Fermat's so-called 'little theorem' - is, in the equivalent formulation
Let p be a prime and a not divisible by p. Then p divides ap-1 - 1.
the basis of most of the widespread fast primality tests (for example Miller-Rabin) and variants or analogues of that appear in even more (e.g. Lucas-Selfridge).
So if we want to know if a not too small odd number n is a prime (even and small numbers are efficiently treated by trial division), we can choose any number a (> 1) which is not a multiple of n, for example 2, and check whether n divides an-1 - 1. Since an-1 becomes huge, that is most efficiently done by checking whether
a^(n-1) ≡ 1 (mod n), i.e. by modular exponentiation. If that congruence doesn't hold, we know that n is composite. If it holds, however, we cannot conclude that n is prime, for example 2^340 ≡ 1 (mod 341), but 341 = 11 * 31 is composite. Composite numbers n such that a^(n-1) ≡ 1 (mod n) are called Fermat pseudoprimes for the base a.
But such occurrences are rare. Given any base a > 1, although there are an infinite number of Fermat pseudoprimes to base a, they are much rarer than actual primes. For example, there are only 78 base-2 Fermat pseudoprimes and 76 base-3 Fermat pseudoprimes below 100000, but 9592 primes. So if one chooses an arbitrary odd n > 1 and an arbitrary base a > 1 and finds a^(n-1) ≡ 1 (mod n), there's a good chance that n is actually prime.
However, we are in a slightly different situation, we are given n and can only choose a. So, for an odd composite n, for how many a, 1 < a < n-1 can a^(n-1) ≡ 1 (mod n) hold?
Unfortunately, there are composite numbers - Carmichael numbers - such that the congruence holds for every a coprime to n. That means that to identify a Carmichael number as composite with the Fermat test, we have to pick a base that is a multiple of one of n's prime divisors - there may not be many such multiples.
But we can strengthen the Fermat test so that composites are more reliably detected. If p is an odd prime, write p-1 = 2*m. Then, if 0 < a < p,
a^(p-1) - 1 = (a^m + 1) * (a^m - 1)
and p divides exactly one of the two factors (the two factors differ by 2, so their greatest common divisor is either 1 or 2). If m is even, we can split a^m - 1 in the same way. Continuing, if p-1 = 2^s * k with k odd, write
a^(p-1) - 1 = (a^(2^(s-1)*k) + 1) * (a^(2^(s-2)*k) + 1) * ... * (a^k + 1) * (a^k - 1)
then p divides exactly one of the factors. This gives rise to the strong Fermat test,
Let n > 2 be an odd number. Write n-1 = 2^s * k with k odd. Given any a with 1 < a < n-1, if
a^k ≡ 1 (mod n) or
a^((2^j)*k) ≡ -1 (mod n) for any j with 0 <= j < s
then n is a strong (Fermat) probable prime for base a. A composite strong base a (Fermat) probable prime is called a strong (Fermat) pseudoprime for the base a. Strong Fermat pseudoprimes are even rarer than ordinary Fermat pseudoprimes, below 1000000, there are 78498 primes, 245 base-2 Fermat pseudoprimes and only 46 base-2 strong Fermat pseudoprimes. More importantly, for any odd composite n, there are at most (n-9)/4 bases 1 < a < n-1 for which n is a strong Fermat pseudoprime.
So if n is an odd composite, the probability that n passes k strong Fermat tests with randomly chosen bases between 1 and n-1 (exclusive bounds) is less than 1/4^k.
A strong Fermat test takes O(log n) steps, each step involves one or two multiplications of numbers with O(log n) bits, so the complexity is O((log n)^3) with naive multiplication [for huge n, more sophisticated multiplication algorithms can be worthwhile].
The Miller-Rabin test is the k-fold strong Fermat test with randomly chosen bases. It is a probabilistic test, but for small enough bounds, short combinations of bases are known which give a deterministic result.
Strong Fermat tests are part of the deterministic APRCL test.
It is advisable to precede such tests with trial division by the first few small primes, since divisions are comparatively cheap and that weeds out most composites.
For the problem of finding the nth prime, in the range where testing all numbers for primality is feasible, there are known combinations of bases that make the multiple strong Fermat test correct, so that would give a faster - O(n*(log n)4) - algorithm.
For n < 2^32, the bases 2, 7, and 61 are sufficient to verify primality. Using that, the hundred-millionth prime is found in about six minutes.
Eliminating composites by prime divisors, the Sieve of Eratosthenes
Instead of investigating the numbers in sequence and checking whether each is prime from scratch, one can also consider the whole set of relevant numbers as one piece and eliminate the multiples of a given prime in one go. This is known as the Sieve of Eratosthenes:
To find the prime numbers not exceeding N
make a list of all numbers from 2 to N
for each k from 2 to N: if k is not yet crossed off, it is prime; cross off all multiples of k as composites
The primes are the numbers in the list which aren't crossed off.
This algorithm is fundamentally different from trial division, although both directly use the divisibility characterisation of primes, in contrast to the Fermat test and similar tests which use other properties of primes.
In trial division, each number n is paired with all primes not exceeding the smaller of √n and the smallest prime divisor of n. Since most composites have a very small prime divisor, detecting composites is cheap here on average. But testing primes is expensive, since there are relatively many primes below √n. Although there are many more composites than primes, the cost of testing primes is so high that it completely dominates the overall running time and renders trial division a relatively slow algorithm. Trial division for all numbers less than N takes O(N1.5 / (log N)²) steps.
In the sieve, each composite n is paired with all of its prime divisors, but only with those. Thus there the primes are the cheap numbers, they are only ever looked at once, while the composites are more expensive, they are crossed off multiple times. One might believe that since a sieve contains many more 'expensive' numbers than 'cheap' ones, it would overall be a bad algorithm. However, a composite number does not have many distinct prime divisors - the number of distinct prime divisors of n is bounded by log n, but usually it is much smaller, the average of the number of distinct prime divisors of the numbers <= n is log log n - so even the 'expensive' numbers in the sieve are on average no more (or hardly more) expensive than the 'cheap' numbers for trial division.
Sieving up to N, for each prime p, there are Θ(N/p) multiples to cross off, so the total number of crossings-off is Θ(∑ (N/p)) = Θ(N * log (log N)). This yields much faster algorithms for finding the primes up to N than trial division or sequential testing with the faster primality tests.
There is, however, a disadvantage to the sieve, it uses O(N) memory. (But with a segmented sieve, that can be reduced to O(√N) without increasing the time complexity.)
For finding the nth prime, instead of the primes up to N, there is also the problem that it is not known beforehand how far the sieve should reach.
The latter can be solved using the prime number theorem. The PNT says
π(x) ~ x/log x (equivalently: lim π(x)*log x/x = 1),
where π(x) is the number of primes not exceeding x (here and below, log must be the natural logarithm, for the algorithmic complexities it is not important which base is chosen for the logarithms). From that, it follows that p(n) ~ n*log n, where p(n) is the nth prime, and there are good upper bounds for p(n) known from deeper analysis, in particular
n*(log n + log (log n) - 1) < p(n) < n*(log n + log (log n)), for n >= 6.
So one can use that as the sieving limit, it doesn't exceed the target far.
The O(N) space requirement can be overcome by using a segmented sieve. One can then record the primes below √N for O(√N / log N) memory consumption and use segments of increasing length (O(√N) when the sieve is near N).
There are some easy improvements on the algorithm as stated above:
start crossing off multiples of p only at p², not at 2*p
eliminate the even numbers from the sieve
eliminate the multiples of further small primes from the sieve
None of these reduce the algorithmic complexity, but they all reduce the constant factors by a significant amount (as with trial division, the elimination of multiples of p yields lesser speedup for larger p while increasing the code complexity more than for smaller p).
Using the first two improvements yields
// Entry k in the array represents the number 2*k+3, so we have to do
// a bit of arithmetic to get the indices right.
public static int nthPrime(int n) {
if (n < 2) return 2;
if (n == 2) return 3;
int limit, root, count = 1;
limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
root = (int)Math.sqrt(limit) + 1;
limit = (limit-1)/2;
root = root/2 - 1;
boolean[] sieve = new boolean[limit];
for(int i = 0; i < root; ++i) {
if (!sieve[i]) {
++count;
for(int j = 2*i*(i+3)+3, p = 2*i+3; j < limit; j += p) {
sieve[j] = true;
}
}
}
int p;
for(p = root; count < n; ++p) {
if (!sieve[p]) {
++count;
}
}
return 2*p+1;
}
which finds the hundred-millionth prime, 2038074743, in about 18 seconds. This time can be reduced to about 15 seconds (here, YMMV) by storing the flags packed, one bit per flag, instead of as booleans, since the reduced memory usage gives better cache locality.
Packing the flags, eliminating also multiples of 3 and using bit-twiddling for faster faster counting,
// Count number of set bits in an int
public static int popCount(int n) {
n -= (n >>> 1) & 0x55555555;
n = ((n >>> 2) & 0x33333333) + (n & 0x33333333);
n = ((n >> 4) & 0x0F0F0F0F) + (n & 0x0F0F0F0F);
return (n * 0x01010101) >> 24;
}
// Speed up counting by counting the primes per
// array slot and not individually. This yields
// another factor of about 1.24 or so.
public static int nthPrime(int n) {
if (n < 2) return 2;
if (n == 2) return 3;
if (n == 3) return 5;
int limit, root, count = 2;
limit = (int)(n*(Math.log(n) + Math.log(Math.log(n)))) + 3;
root = (int)Math.sqrt(limit);
switch(limit%6) {
case 0:
limit = 2*(limit/6) - 1;
break;
case 5:
limit = 2*(limit/6) + 1;
break;
default:
limit = 2*(limit/6);
}
switch(root%6) {
case 0:
root = 2*(root/6) - 1;
break;
case 5:
root = 2*(root/6) + 1;
break;
default:
root = 2*(root/6);
}
int dim = (limit+31) >> 5;
int[] sieve = new int[dim];
for(int i = 0; i < root; ++i) {
if ((sieve[i >> 5] & (1 << (i&31))) == 0) {
int start, s1, s2;
if ((i & 1) == 1) {
start = i*(3*i+8)+4;
s1 = 4*i+5;
s2 = 2*i+3;
} else {
start = i*(3*i+10)+7;
s1 = 2*i+3;
s2 = 4*i+7;
}
for(int j = start; j < limit; j += s2) {
sieve[j >> 5] |= 1 << (j&31);
j += s1;
if (j >= limit) break;
sieve[j >> 5] |= 1 << (j&31);
}
}
}
int i;
for(i = 0; count < n; ++i) {
count += popCount(~sieve[i]);
}
--i;
int mask = ~sieve[i];
int p;
for(p = 31; count >= n; --p) {
count -= (mask >> p) & 1;
}
return 3*(p+(i<<5))+7+(p&1);
}
finds the hundred-millionth prime in about 9 seconds, which is not unbearably long.
There are other types of prime sieves, of particular interest is the Sieve of Atkin, which exploits the fact that certain congruence classes of (rational) primes are composites in the ring of algebraic integers of some quadratic extensions of ℚ. Here is not the place to expand on the mathematical theory, suffice it to say that the Sieve of Atkin has lower algorithmic complexity than the Sieve of Eratosthenes and hence is preferable for large limits (for small limits, a not overly optimised Atkin sieve has higher overhead and thus can be slower than a comparably optimised Eratosthenes sieve).
D. J. Bernstein's primegen library (written in C) is well optimised for numbers below 232 and finds the hundred-millionth prime (here) in about 1.1 seconds.
The fast way
If we only want to find the nth prime, there is no intrinsic value in also finding all the smaller primes. If we can skip most of them, we can save a lot of time and work. Given a good approximation a(n) to the nth prime p(n), if we have a fast way to calculate the number of primes π(a(n)) not exceeding a(n), we can then sieve a small range above or below a(n) to identify the few missing or excess primes between a(n) and p(n).
We have seen an easily computed fairly good approximation to p(n) above, we could take
a(n) = n*(log n + log (log n))
for example.
A good method to compute π(x) is the Meissel-Lehmer method, which computes π(x) in roughly O(x^0.7) time (the exact complexity depends on the implementation, a refinement by Lagarias, Miller, Odlyzko, Deléglise and Rivat lets one compute π(x) in O(x2/3 / log² x) time).
Starting with the simple approximation a(n), we compute e(n) = π(a(n)) - n. By the prime number theorem, the density of primes near a(n) is about 1/log a(n), so we expect p(n) to be near b(n) = a(n) - log a(n)*e(n) and we would sieve a range slightly larger than log a(n)*e(n). For greater confidence that p(n) is in the sieved range, one can increase the range by a factor of 2, say, which almost certainly will be large enough. If the range seems too large, one can iterate with the better approximation b(n) in place of a(n), compute π(b(n)) and f(n) = π((b(n)) - n. Typically, |f(n)| will be much smaller than |e(n)|. If f(n) is approximately -e(n), c(n) = (a(n) + b(n)) / 2 will be a better approximation to p(n). Only in the very unlikely case that f(n) is very close to e(n) (and not very close to 0), finding a sufficiently good approximation to p(n) that the final sieving stage can be done in time comparable to computing π(a(n)) becomes a problem.
In general, after one or two improvements to the initial approximation, the range to be sieved is small enough for the sieving stage to have a complexity of O(n^0.75) or better.
This method finds the hundred-millionth prime in about 40 milliseconds, and the 1012-th prime, 29996224275833, in under eight seconds.
tl;dr: Finding the nth prime can be efficiently done, but the more efficient you want it, the more mathematics is involved.
I have Java code for most of the discussed algorithms prepared here, in case somebody wants to play around with them.
¹ Aside remark for overinterested souls: The definition of primes used in modern mathematics is different, applicable in much more general situations. If we adapt the school definition to include negative numbers - so a number is prime if it's neither 1 nor -1 and divisible only by 1, -1, itself and its negative - that defines (for integers) what is nowadays called an irreducible element of ℤ, however, for integers, the definitions of prime and irreducible elements coincide.
int counter = 0;
for(int i = 1; ; i++) {
if(isPrime(i)
counter++;
if(counter == userInput) {
print(i);
break;
}
}
Edit: Your prime function could use a bit of work. Here's one that I have written:
private static boolean isPrime(long n) {
if(n < 2)
return false;
for (long i = 2; i * i <= n; i++) {
if (n % i == 0)
return false;
}
return true;
}
Note - you only need to go up to sqrt(n) when looking at factors, hence the i * i <= n
You are trying to do too much in the main method. You need to break this up into more manageable parts. Write a method boolean isPrime(int n) that returns true if a number is prime, and false otherwise. Then modify the main method to use isPrime.
java.math.BigInteger has a nextProbablePrime() method. Whilst I'm guessing this is meant for cryptography you could use it for you work.
BigInteger prime = BigInteger.valueOf(0);
for (int i = 0; i < n; i++) {
prime = prime.nextProbablePrime();
}
System.out.println(prime.intValue());
Although many correct and detailed explanations are available. but here is my
C implementation:
#include<stdio.h>
#include<conio.h>
main() {
int pk, qd, am, no, c = 0;
printf("\n Enter the Number U want to Find");
scanf("%d", & no);
for (pk = 2; pk <= 1000; pk++) {
am = 0;
for (qd = 2; qd <= pk / 2; qd++) {
if (pk % qd == 0) {
am = 1;
break;
}
}
if (am == 0)
c++;
if (c == no) {
printf("%d", pk);
break;
}
}
getch();
return 0;
}
public class prime{
public static void main(String ar[])
{
int count;
int no=0;
for(int i=0;i<1000;i++){
count=0;
for(int j=1;j<=i;j++){
if(i%j==0){
count++;
}
}
if(count==2){
no++;
if(no==Integer.parseInt(ar[0])){
System.out.println(no+"\t"+i+"\t") ;
}
}
}
}
}
I can see that you have received many correct answers and very detailed one. I believe you are not testing it for very large prime numbers. And your only concern is to avoid printing intermediary prime number by your program.
A tiny change your program will do the trick.
Keep your logic same way and just pull out the print statement outside of loop.
Break outer loop after n prime numbers.
import java.util.Scanner;
/**
* Calculates the nth prime number
* #author {Zyst}
*/
public class Prime {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n,
i = 2,
x = 2;
System.out.printf("This program calculates the nth Prime number\n");
System.out.printf("Please enter the nth prime number you want to find:");
n = input.nextInt();
for(i = 2, x = 2; n > 0; i++) {
for(x = 2; x < i; x++) {
if(i % x == 0) {
break;
}
}
if(x == i) {
n--;
}
}
System.out.printf("\n%d is prime", x);
}
}
This program is an efficient one. I have added one more check-in if to get the square root of a number and check is it divisible or not if it's then its not a prime number. this will solve all the problems efficiently.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T; // number of test cases
T = sc.nextInt();
long[] number = new long[T];
if(1<= T && T <= 30){
for(int i =0;i<T;i++){
number[i]=sc.nextInt(); // read all the numbers
}
for(int i =0;i<T;i++){
if(isPrime(number[i]))
System.out.println("Prime");
else
System.out.println("Not prime");
}
}
else
return;
}
// is prime or not
static boolean isPrime(long num){
if(num==1)
return false;
if(num <= 3)
return true;
if(num % 2 == 0 || num % 3 == 0 || num % (int)Math.sqrt(num) == 0)
return false;
for(int i=4;i<(int)Math.sqrt(num);i++){
if(num%i==0)
return false;
}
return true;
}
An another solution
import java.util.Scanner;
public class Prime {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int[] arr = new int[10000000];
for(int i=2;i<10000000;i++)
{
arr[i]=i;
}
for(int i=2;i<10000000;i++)
for(int j=i+i;j<10000000;j+=i)
arr[j]=0;
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
int n = in.nextInt();
int count=0;
for(int j=2;j<10000000;j++)
{
if(arr[j]!=0)
{
count++;
if(count==n)
{
System.out.println(j);
break;
}
}
}
}
}
}
Hope this will help for larger numbers...
I just added the missing lines in your own thought process.
static int nthPrimeFinder(int n) {
int counter = 1; // For 1 and 2. assuming n is not 1 or 2.
int i = 2;
int x = 2;
int tempLength = n;
while (counter <= n) {
for (; i <= tempLength; i++) {
for (x = 2; x < i; x++) {
if (i % x == 0) {
break;
}
}
if (x == i && counter < n) {
//System.out.printf("\n%d is prime", x);
counter++;
if (counter == n) {
System.out.printf("\n%d is prime", x);
return counter;
}
}
}
tempLength = tempLength+n;
}
return 0;
}
Using Java 8 parallelStream would be faster. Below is my code for finding Nth prime number
public static Integer findNthPrimeNumber(Integer nthNumber) {
List<Integer> primeList = new ArrayList<>();
primeList.addAll(Arrays.asList(2, 3));
Integer initializer = 4;
while (primeList.size() < nthNumber) {
if (isPrime(initializer, primeList)) {
primeList.add(initializer);
}
initializer++;
}
return primeList.get(primeList.size() - 1);
}
public static Boolean isPrime(Integer input, List<Integer> primeList) {
return !(primeList.parallelStream().anyMatch(i -> input % i == 0));
}
#Test
public void findNthPrimeTest() {
Problem7 inputObj = new Problem7();
Integer methodOutput = inputObj.findNthPrimeNumber(100);
Assert.assertEquals((Integer) 541, methodOutput);
Assert.assertEquals((Integer) 104743, inputObj.findNthPrimeNumber(10001));
}

Categories

Resources