Java Prime Checker - java

if found a prime checker in java, which uses this method.
Can somebody explain, why the for-loop goes to the square root of the searched prime number? - Is there a more efficient way of doing this?
- Thank you!
public static boolean isPrime(int p){
if(p % 2 == 0 || p < 2){
return false;
}
else {
System.out.println("Sqare: " + (int)Math.sqrt(p));
for(int i = 3; i <= (int)Math.sqrt(p); i = i+2){
if(p % i == 0){
return false;
}
}
}
return true;
}

If a number is not prime, then it has at least two factors: 63 = 7 x 9 or 121 = 11 x 11 for example. The smaller of the two factors has to be less than or equal to the square root of the original number. If you find any factor, then the number is not prime so you can stop searching once you have found the first factor.
By searching up to and including the square root you are guaranteed to find a factor of a composite number. If the search reaches past the square root without finding a factor, then the number must be prime with factors 1 and the number itself. There is no need to carry on searching beyond the square root as you will not learn anything new and will waste time.

Related

Find max matching 3 Triangular numbers

It's well known that any positive number can be expressed through at most 3 Triangular numbers. (
https://oeis.org/A000217 )
Example:
11 := 10 + 1
12 := 10 + 1 + 1
13 := 10 + 3
14 := 10 + 3 + 1
15 := 15
I am searching the representation of the positive number n through at most 3 possible Triangular summands. There can exist more than one representation of n. I am interested in the one with the greatest summands.
Is there a more effective way than 2 decreasing for and 1 increasing for loops to find the summands?
public void printMaxTriangularNumbers(int n){
int[] tri = createTriangularNumbers(1000);
lbl: for(int i = tri.length-1; ; i--){
int tmp = n - tri[i];
if(tmp == 0){
System.out.println(tri[i]);
break;
}
for(int j=i; j>0; j--){
int tmp2 = tmp - tri[j];
if(tmp2 ==0){
System.out.println(tri[i]);
System.out.println(tri[j]);
break lbl;
}
for(int k=1; k <= j;k++){
if(tmp2 - tri[k] == 0){
System.out.println(tri[i]);
System.out.println(tri[j]);
System.out.println(tri[k]);
break lbl;
}
}
}
}
}
public int[] createTriangularNumbers(int n){
int[] out = new int[n+1];
for(int i=1,sum=0; i<=n;i++){
out[i] = sum += i;
}
return out;
}
As far as I can see, there is no direct formula. An algorithm is needed. For instance, a greedy method does not work. Take for example the value 90:
The greatest triangular number not greater than 90 is 78. Remains 12
The greatest triangular number not greater than 12 is 10. Remains 2
And now it becomes clear we will need 4 terms which is not acceptable.
So I would propose a recursive/backtracking algorithm, where each recursive call deals with one summand only. Each level in the recursion takes first the highest possible triangular number, but if the recursive call fails, it will go for the second largest and dive into recursion again, until there is an acceptable sum.
We can use the formula mentioned at maths.stackexchange.com:
Let Tm be the largest triangular number less than or equal to c.
You can actually get an explicit formula for m, namely:
Here is a snippet that implements the recursion. When running it, you can introduce a value, and the triangular summands will be produced for it.
function getTriangularTerms(n, maxTerms) {
if (maxTerms === 0 && n > 0) return null; // failure: too many terms
if (n == 0) return []; // Ok! Return empty array to which terms can be prepended
// Allow several attempts, each time with a
// lesser triangular summand:
for (let k = Math.floor((Math.sqrt(1+8*n) - 1) / 2); k >= 1; k--) {
let term = k * (k+1)/2;
// Use recursion
let result = getTriangularTerms(n - term, maxTerms - 1);
// If result is not null, we have a match
if (result) return [term, ...result]; // prepend term
}
}
// I/O handling
let input = document.querySelector("input");
let output = document.querySelector("span");
(input.oninput = function () { // event handler for any change in the input
let n = input.value;
let terms = getTriangularTerms(n, 3); // allow 3 terms max.
output.textContent = terms.join("+");
})(); // execute also at page load.
Enter number: <input type="number" value="14"><br>
Terms: <span></span>
Since a triangular number is any number t that satisfies t=x(x+1)/2 for any natural number x, what you're asking is to solve
n = a(a+1)/2 + b(b+1)/2 + c(c+1)/2
and to find the solution (a,b,c) with greatest possible max(a,b,c). You didn't specify that you only allow solutions with 3 triangular numbers, so I will assume you also allow solutions of the form (a,b,c,d) and look for the one with the greatest max(a,b,c,d).
There might be multiple solutions, but one with at most 3 triangular numbers always exists. Since it's possible to form any number with 3 triangular numbers, you can find the largest triangular number t with t<=n, and then it will follow n=t+d, where d=n-t. d is a natural number >=0 and therefore can be composed by 3 triangular numbers itself. Since you're interested in the largest summand, the largest will be t, which can be computed with t=x(x+1)/2 where x=floor((sqrt(1+8n)-1)/2) (obtained by solving the formula n=x(x+1)/2+d).
As a practical example, take n=218. With the formula, we get x=20 and t=210, which indeed is the largest triangular number before 218. The other triangular numbers, in this case, will be 6, 1, 1 since the only way to compute 8 is with those.

I have a program that calculates the first 200 prime numbers, but I do not understand a formula in it

I need to write a code which should calculate the first 200 prime numbers, but I can't hand it in as long as I can't explain everything. I used a piece of code from the internet as reference (http://crab.rutgers.edu/~dhong/cs325/chapter3/PrimeNumber.java).
Whole code:
public class Opdracht3 {
public static void main(String[] args) {
int limiet = 200;
int counter = 1;
int testpriem = 3;
boolean isPriem;
while (counter <= limiet) {
isPriem = true;
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
if (isPriem) {
System.out.println(counter + ": " + testpriem);
counter++;
}
testpriem++;
}
}
}
Below part of code verifies if the number is a composite. If testpriem is composite, then comes out of the loop and starts over. Otherwise, it continues and prints the prime number testpriem.
The problem is here:
for (int i = 2; i <= testpriem / 2; i++) {
if (testpriem % i == 0) {
isPriem = false;
break;
}
}
I tested what happens to i, and one way or another it recognizes the divisor needed to calculate the composite. (With 4 divisor is 2, with 9 divisor is 3, with 221 divisor is 13) But I am flabbergasted as of why.
Any ideas?.
the % or ("remainder") operator in Java divides one operand by another and returns the remainder as its result. And of course if integer x is evenly divisible by another integer y (meaning x/y = some integer z with a remainder of zero), then x can not be prime.
First remember every number able to divide by its half or less. Consider number 7 it is possible divided by 1,2,3 because after 3, if try to divide number by 4 means 4x2 = 8 that is greater than 7. so it is optimum way to find divisor in this way. One more thing every number divided by 1 and number itself. so if number number is divided by 1 or itself then it is called prime so i starts from 2.
now consider testpriem =7 so you will get loop like
for (int i = 2; i <= 7 / 2(i.e 3); i++)
{
if(7 % i == 0)
{
isPriem = false;
break;
}
so first time it checks 7%2=1 so condition false. again check for 7%3 = 1 again condition false. and now this condition full fills here i <= 7 / 2(i.e 3) so loop stopped and it result 7 number is prime
Well, if testpriem % i == 0, it means that i divides testpriem, which means that testpriem is not a prime a number and i, is its first divider. % is the modulo operation, which is the rest of the division.
https://en.wikipedia.org/wiki/Modulo_operation
The break stops the for loop and moves to the next position in the while loop. So it does not restart the for loop for the current tested number.
The break is used for efficiency reasons. You could remove it and the algorithm would still work correctly but slower.

to find a prime number in java

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.

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.

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