find nth prime in java with low time complexity - java

I'm trying to find a low time complexity solution for finding nth prime.
However there's some method problems I'm quite confused.
Also I want to know is mine has a low time complexity or can it be better?
I've tried two different ways to find the prime while the first one is way too slow, so i changed another one. But the boolean method has some problem which i have no idea.
public static int FInd_NthPrime(int n){
int num=0,j,c=2;
while (true) {
if(isPrime(c)){
num = num+1;
}
c = c+1;
break;
}
return c; // the error happened
}
public static boolean isPrime(int n) {
for (int i = 2; i < Math.sqrt(n); i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
public static void print_nth_prime(int num){
int result = FInd_NthPrime(num);
System.out.print(num +" "+result);
}
I expect anyone tell me the mistake in boolean method and is there any better way to make low time complexity for finding the nth prime。

You only have to test odd integers and special case "2".
And when doing the isPrime test, just do the modulo check against existing primes already discovered.
public static int FInd_NthPrime(int n){
int val = 3; // first odd number greater than 2
int result = 0;
if (n <= 1) {
return 2; // special case for 2, the only even prime
}
// build up a Hash table of all discovered primes so far
ArrayList<Integer> primes = new ArrayList<Integer>();
primes.add(2);
while (n > 1) {
if (isPrime(val, primes)) {
n--;
result = val;
}
val += 2; // increment to the next odd integer
}
return result;
}
public static boolean isPrime(int n, ArrayList<Integer> primes) {
if (n == 2) {
return true;
}
int stop = (int)Math.sqrt(n);
for (int divisor : primes) {
if ((n % divisor) == 0) {
return false;
}
if (divisor > stop) {
break;
}
}
//System.out.format("Added %d to prime list\n", n);
primes.add(n);
return true;
}

Related

Optimal way to find next prime number (Java)

I was asked to write a program to find next prime number in an optimal way. I wrote this code, but I could not find an optimal answer to it. Any suggestions?
public static int nextPrime(int input) {
input++;
//now find if the number is prime or not
for(int i=2;i<input;i++) {
if(input % i ==0 ) {
input++;
i=2;
}
else{
continue;
}
}
return input;
}
public int nextPrime(int input){
int counter;
input++;
while(true){
int l = (int) sqrt(input);
counter = 0;
for(int i = 2; i <= l; i ++){
if(input % i == 0) counter++;
}
if(counter == 0)
return input;
else{
input++;
continue;
}
}
}
There is no need to check up on input number. It is enough to check up to the square root of a number. Sorry, I didn't remember the theorem name. Here we are incrementing the input for next prime.
The time complexity of this solution O(n^(3/2)).
#Ephraim - I've replaced the recursive code with "while" loop. It's running more faster.
int nextPrime(int M) {
while(!isPrime(++M))
// no need ++M; as I already added in the isPrime method's parameter.
return M;
}
boolean isPrime(int M) {
for(int i = 2; i <= M; i++)
if(M % i == 0)
return false;
return true;
}
#Scott Parent- I've tested the the recursive code; "while" loop and steam code (IntStream and LongStream) - the Stream's code is running slowly, very slowly.
Example:
Input value: 60000000000
Output: 60000000029
Elapsed time for recursive algorithm = 7 milliseconds
Output: 60000000029
Elapsed time for traversal algorithm = 4 milliseconds
Output: 60000000029
Elapsed time for LongStream.range(2, number).noneMatch(...) algorithm = 615825 milliseconds
If I use IntStream - the elapsed time is about 230 milliseconds for the max Integer number. It's too much slowly. The "while" loop in nextPrime(int n) is running 1-4 milliseconds for the max integer number, but usage of LongStream for 600000000000 input value - the result I couldnt see in 1 hour.
I'm running now for the 600000000000 long number:
Elapsed time for recursive algorithm = 36 milliseconds
Output: 60000000029
Elapsed time for traversal algorithm = 27 milliseconds
Output: 60000000029
Elapsed time for LongStream.range(2, number).noneMatch(...)
it's still running more than 58 minutes, but it's not finished yet.
long n = 12345;
BigInteger b = new BigInteger(String.valueOf(n));
long res = Long.parseLong(b.nextProbablePrime().toString());
System.out.println("Next prime no. is "+ res);
Generate all prime numbers up to your limit using sieve of eratosthenes. And then input your number n and search if n> prime[i] , prime[i] is the answer.
You can also do the same using recursions like this:
int nextPrime(int M) {
if(!isPrime(M)) M = nextPrime(++M);
return M;
}
boolean isPrime(int M) {
for(int i = 2; i <= Math.sqrt(M); i++)
if(M % i == 0) return false;
return true;
}
My son has written his own algorithm - in one method.
But it's written on python - you can find it here.
On Java it looks like:
static long nextPrime(long number) {
boolean prime = false;
long n = number;
while (!prime && n < number * 2) {
n++;
prime = true;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
prime = false;
break;
}
}
}
return n;
}
Here I add a solution algorithm. First of all, the while loop grabs the next number to be tested within the range of number + 1 to number * 2. Then the number is sent to the isPrime method (which uses Java 8 streams) that iterates the stream to look for numbers that have no other factors.
private static int nextPrime(final int number) {
int i = number + 1;
while (!isPrime(i) && i < number * 2)
i++;
return i;
}
private static boolean isPrime(final int number) {
return number > 1 && IntStream.range(2, number).noneMatch(index -> number % index == 0);
}
Dude check this code.
isPrime() in the while loop checks for the next prime number after incrementing the current prime/non-prime number. I did used the long datatype (that's what I got as assignment).
if (isPrime(num)) {
System.out.println("Current Prime number: " + num);
} else {
long a = getNextPrime(num);
System.out.println("Next Prime:" + a);
}
public static long getNextPrime(long num) {
long nextPrime = 0;
while (true) {
num++;
boolean x = isPrime(num);
if (x) {
nextPrime = num;
break;
}
}
return nextPrime;
}
public static boolean isPrime(long num) {
if (num == 0 || num == 1) {
return false;
}
for (long i = 2; i <= num / 2; ++i) {
if (num % i == 0) {
return false;
}
}
return true;
}
This is functional way of finding next prime number.
public void printFirstNPrimes(long n) {
Stream.iterate(2, i->nextPrime(i))
.limit(n).forEach(System.out::println);
}
public static boolean isPrime(long x) {
return Stream.iterate(2, i->i+1)
.limit((long)(Math.sqrt(x)))
.allMatch(n -> x % n != 0);
}
public static int nextPrime(int x) {
return isPrime(x+1)? x+1 : nextPrime(x+1);
}
So, I was reading the first answer and saw some potential upgrades.
I made them and got a really significant improvement.
The original code could calculate 200000 prime numbers in 22.32s
With a little changes I managed to execute the same operation in 11.41s, with the same results.
Notice I executed the code on my laptop #2.50 GHz, running on IntelIJ.
public static int nextPrime(int n) {
boolean isPrime;
n++;
while (true) {
int sqrt = (int) Math.sqrt(n);
isprime = true;
for (int i = 2; i <= sqrt; i++) {
if (n % i == 0) isPrime = false;
}
if (isPrime)
return n;
else {
n++;
}
}
}
Hope you like it!
public class ClosestPrimeNumber {
static boolean isPrime(int n) {
for (int x = 2; x <= Math.sqrt(n); x++) {
if (n % x ==0) {
return false;
}
}
return true;
}
static int next_forward = 0;
static int next_backward = 0;
static int next = 0;
static int closestPrimeNumberForward(int n) {
if (isPrime(n)) {
next_forward = n;
return next_forward;
}else {
next_forward = n+1;
closestPrimeNumberForward(next_forward);
}
return next_forward;
}
static int closestPrimeNumberBackward(int n) {
if (isPrime(n)) {
next_backward = n;
return next_backward;
}else {
next_backward = n-1;
closestPrimeNumberBackward(next_backward);
}
return next_backward;
}
static int closestCompare(int forward, int backward, int num) {
return (Math.abs(num-backward) > Math.abs(num-forward) ) ? forward : backward;
}
public static void main(String[] args) {
int valor = 102;
System.out.println(closestCompare(closestPrimeNumberForward(valor), closestPrimeNumberBackward(valor), valor));
}
}
public int nextPrime(int input){
int counter;
while(true){
counter = 0;
for(int i = 1; i <= input; i ++){
if(input % i == 0) counter++;
}
if(counter == 2)
return input;
else{
input++;
continue;
}
}
}
This will return the nextPrime but cannot say is most optimal way
It is simple as it execute an infinite while loop which break when
prime number is returned.
In while is finds whether the number is prime or not
If it is prime it returns that number, if not it increment input and continue the while loop

Slow calculation of sum of primes for large datasets [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
My program that calculates the sum of primes is very slow for very large nth term. Please how do I optimize the processing time of my program? The fastest program will be appreciated and the reason why mine is slow for large sets of data. Thanks.
Here's the Java program:
public class SumOfPrimes {
public static void main(String[] args) {
primeNumber(2000000);
}
public static void primeNumber(int nth) {
int counter = 0, i = 2;
while(i>=2) {
if(isPrime(i)) {
counter += i;
}
i++;
if(i == nth) {
break;
}
}
System.out.println(counter);
}
public static boolean isPrime(int n) {
boolean prime = true;
int i;
for(i= 2; i < n; i++) {
if (n % i == 0) {
prime = false;
for (int j = 3; j * j < n; j += 2) {
if (n % j == 0) prime = false;
}
}
}
return prime;
}
}
Well, it's unclear why you have an inner for loop in your isPrime. Removing it will save much time.
Besides, once you find that n is not prime, you should return immediately. Either break out of the loop, or just return false.
Another optimization would be not to test all the number until i < n. It's enough to test until i * i <= n.
public static boolean isPrime(int n) {
int i;
for(i = 2; i * i <= n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
Remember primes you have found, and only test them.
Remove the inner loop.
Test 2, 3, then all odds.
Something like...
public boolean isPrime( ArrayList<Long> primes, long n ){
for( Long t : primes ){
if( n % t == 0 ){
return false;
}
if( t * t > n )return true;
}
return true;
}
public void sumOfPrimes()
{
ArrayList<Long> primes = new ArrayList<Long>();
long n;
double count = 0;
for( n = 2; n < 2000000; n++ ){
if( isPrime( primes, n ) ){
primes.add( n );
count += n;
}
}
}
This should be your isPrime function-
bool isPrime (int number) {
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
for (int i=3; (i*i) <= number; i+=2) {
if (number % i == 0 ) return false;
}
return true;
}
Putting together all the answers to my question above, my program has been re-written and it is much faster for very large datasets.
public class SumOfPrimes {
public static void main(String[] args) {
primeNumber(2000000);
}
public static void primeNumber(int nth) {
int i = 2;
long counter = 0;
while(i>=2) {
if(isPrime(i)) {
counter += i;
}
i++;
if(i == nth) {
break;
}
}
System.out.println(counter);
}
public static boolean isPrime (int n) {
if (n < 2) return false;
if (n == 2) return true;
if (n % 2 == 0) return false;
for (int i=3; (i*i) <= n; i+=2) {
if (n % i == 0 ) return false;
}
return true;
}
}
#aega's solution for the isPrime function did the trick. Now 2 million datasets can be calculated for less than 2 secs.
We no need to test from 1 to n, even 3 to n/2 or 3 to sqrt(n) is also too much for testing for a bigger number.
To make the testing the least, we can only test n with the previous prime that have been found up to sqrt(n), like what mksteve has mentioned.
static List<Integer> primes = new ArrayList<>();
static boolean isPrime (int number) {
if (number < 2) return false;
if (number == 2) return true;
if (number % 2 == 0) return false;
int limit = (int) Math.sqrt(number);
for (i : primes) {
if (i > limit) break;
if (number % i == 0 ) return false;
}
return true;
}
public static void primeNumber(int nth) {
int i = 2;
long counter = 0;
while(i <= nth) {
if(isPrime(i)) {
counter += i;
primes.add(i);
}
i++;
}
System.out.println(counter);
}
A faster program will be to store the generated prime numbers in an array and use only those elements for divisibility check. The number of iterations will reduce dramatically. An element of self-learning is there in this.
I don't have time right now. But, when I'm free, will write a java code to implement this.
Use the power of Lambda for dynamic functional referencing and streams for optimized performance with inbuilt filter conditions.
public static boolean isPrime(final int number) {
return IntStream.range(2,(long) Math.ceil(Math.sqrt(number + 1))).noneMatch(x -> number % x == 0);
}

Find Prime Numbers

I am trying to take two arguments from the command line, the first number is the starting point, and the second one is how many prime numbers should be found after that. I need to print the prime numbers found as many times as the second command argument says. I cannot figure out how to make it run the correct amount of times, and after that find the prime number. Here is what I have tried:
int values = Integer.parseInt(args[0]);
int loopAmount = Integer.parseInt(args[1]);
for (int i = 2; i <= loopAmount; i++) {
loopAmount++;
if (values % i != 0) {
values++;
System.out.println(i);
}
}
Your main loop should be something like this:
int start = Integer.parseInt(args[0]);
int count = Integer.parseInt(args[1]);
for (int candidate = start, i = 0; i < count; ++candidate) {
if (isPrime(candidate)) {
i++;
System.out.println(candidate);
}
}
I replaced the variable names to make them more meaningful about their purpose.
Inside the loop, the isPrime method is something you'll have to implement: if the parameter it receives is a prime, return true, otherwise false.
If I understand correctly you want to find N prime numbers starting from X. Code should be pretty simple:
int X = Integer.parseInt(args[0]);
int N = Integer.parseInt(args[1]);
int C = 0;
while (C < N)
{
for(int i=2; i< X; i++)
{
if(X % i == 0){
X++;
continue;
}
}
System.out.println(X);
X++;
C++;
}
An optimized version :
// cache already found primes
final List<Integer> primes = new ArrayList<>();
/**
* Find {#code count} prime numbers starting at {#code start} inclusive
*/
public void findPrimes(int start, int count) {
for (int i = 2; count > 0; i++) {
if (isPrime(i) && i >= start) {
System.out.println(i);
count--;
}
}
}
private boolean isPrime(final int i) {
int sqrt = (int)Math.sqrt(i);
for (int prime : primes) {
if (i % prime == 0) {
return false;
}
if (prime > sqrt) {
break;
}
}
primes.add(i);
return true;
}
We really need to check for divisors only up to sqrt.
We really need to find only prime divisors since any number can be written as a product of prime numbers.
solution
#include <iostream>
using namespace std;
int main() {
int i, n;
bool isPrime = true;
cout << "Enter a positive integer: ";
cin >> n;
// 0 and 1 are not prime numbers
if (n == 0 || n == 1)
{
isPrime = false;
}
else
{
//algorithm to check for prime numbers
for (i = 2; i <= n / 2; ++i)
{
if (n % i == 0)
{
isPrime = false;
break;
}
}
}
if (isPrime)
cout << n << " is a prime number";
else
cout << n << " is not a prime number";
return 0;
}

I can't figure out my error in my PrimeGenerator

In the output, I get a 9 where I should be getting an 11!
This occurs after the fifth call to nextPrime(). Every other output is correct except for the 5th one! I have been struggling to determine my error for a few hours now. Sorry if my code is sloppy, this is the way my mind figured out the problem! It was a requirement to use the flag controlled loop.
public class PrimeGenerator
{
private int num = 2;
public PrimeGenerator()
{
}
public int nextPrime()
{
boolean done = false;
for (int n = num; !isPrime(num); n++)
num = n;
if (isPrime(num))
{
done = true;
}
if (done)
{
int prime = num;
num++;
return prime;
}
return num;
}
public static boolean isPrime(int n)
{
boolean result = true;
for (int i = 2; n % i == 0 && i < n; i++)
result = false;
if (n == 2)
result = true;
return result;
}
}
My Tester just calls the nextPrime() method and prints the result.
You get 9 instead of 11 because you have mistake in method isPrime
public static boolean isPrime(int n)
{
boolean result = true;
for (int i = 2; n % i == 0 && i < n; i++)
result = false;
if (n == 2)
result = true;
return result;
}
Look for number 9.
first iteration: i = 2, result = true
n % i => 9 % 2 = 1, so your loop stops before first iteration and result didn't changed.
Try to change method isPrime (Updated as commented #John in comments)
public static boolean isPrime(int n)
{
if( n % 2 == 0 ) {
return false;
}
double root = Math.sqrt(n);
for ( int i = 3; i < root; i+=2 ) {
if( n % i == 0 ) {
return false;
}
}
return true;
}
Your nextPrime method returns num whether or not it is prime. Your code is effectively:
if(isPrime(num))
return num;
}
return num;
So the main problem with your code here is the method for checking if a number is prime. According to number theory, you just need to check that the given number is not divisible by any number between 2 and the root of the given number you want to determine is prime. More formally, if you want to check if a number n is prime, you need to check that n is not divisible by any number between 2 and sqrt(n).
An updated method using this number theory fact is below:
public static boolean isPrime(int n)
{
int root = (int)Math.sqrt(n);
for (int i = 2; i <= root; i++) {
if(n % i == 0) {
return false;
}
}
return true;
}
With this your determination of the prime number would be correct and would be much faster. There are even faster ways of determining primes and generating primes like sieve's algorithm.

How to factor a number and determine whether its a prime number

So i have this problem where when i factor a number, lets say 15, i have to display this: 15=3x5 but instead what i get is 3x5x5 and i have no clue of how to make it that so it only displays 3x5. And then another problem i have is to find whether the number i inputted is a prime number or not. Any way of fixing this? I just need that and the other stuff im gonna edit after that.
public class PrimeFactor
{
public static void main(String[] args)
{
Scanner input= new Scanner(System.in);
int a;
int d;
int remainder=0;
int count=2;
int c=0;
String s;
System.out.println("Enter an integer to be factored:");
a=input.nextInt();
s="";
d=a;
while(a>1)
{
if(a>1)
{
s="";
while(a>1)
{
remainder=a%count;
if (!(remainder>0))
while(remainder==0)
{
remainder=a%count;
if (remainder==0)
{
a=a/count;
c=c+1;
s=s+count+"x";
if (a==1)
s=s+count;
}
else
count++;
}
else
count++;
}
if (a%count==0)
{
System.out.println(d +"=" + s);
System.out.println(d+" is a prime number.");
}
else
System.out.println(d +"=" + s);
}
// TODO code application logic here
}
}
}
This determines if the number is prime or not the quickest way. Another method would be to use a for loop to determine the number of factors for the number and then say it's prime if it has more than two factors.
int num; // is the number being tested for if it's prime.
boolean isPrime = true;
for (int i = 2; i <= Math.sqrt(num); i++) // only have to test until the square root of the number
{
if (num%i == 0) // if the number is divisible by anything from 2 - the square root of the number
{
isPrime = false; // it is not prime
break; // break out of the loop because it's not prime and no more testing needed
}
}
if (isPrime)
{
System.out.println(num + " is a prime number.");
}
else
{
System.out.println(num + " is a composite number.");
}
You are not constructing the factorization string quite right:
When you find that 3 divides a=15 you set s to 3x and set a to the quotient, so a=5
When you find that 5 divides a=5 you append 5x to s, so now s is 3x5x. Then you set a to the quotient, which is 1. Since the quotient is now 1, you append 5 again, so now you get 3x5x5.
What you'll want to do is append only 5 when a=1, not 5x5. You have to change this:
s=s+count+"x";
if (a==1)
s=s+count;
to this:
if (a==1) {
s=s+count;
} else {
s=s+count+"x";
}
How about trying like this:-
for(int i = input-1; i > 0; i--) {
if((input % i) == 0) {
if(i == 1)
System.out.println("Number is a prime");
else
System.out.println("Number is not a prime");
break;
}
}
These are quite straight-forward methods you can use to factor a number and determine if it is a prime number:
public static int oneFactor(int i) {
for (int j = 2; j < i; j++) {
if (i % j == 0)
return j;
}
return -1;
}
public static Integer[] primeFactors(int i) {
List<Integer> factors = new ArrayList<Integer>();
boolean cont = true;
while (cont) {
int f = oneFactor(i);
if (i > 1 && f != -1) {
i /= f;
factors.add(f);
} else
factors.add(i);
if (f == -1)
cont = false;
}
return factors.toArray(new Integer[factors.size()]);
}
public static boolean isPrime(int i) {
if (i == 2 || i == 3)
return true;
if (i < 2 || i % 2 == 0)
return false;
for (int j = 3, end = (int) Math.sqrt(i); j <= end; j += 2) {
if (i % j == 0) {
return false;
}
}
return true;
}
I am sure one can use faster algorithms, but those would be at the cost of simplicity, and it doesn't seem like you need high speed methods.
They all operate on ints, but its easy to change them to work with longs.
If you have any questions, feel free to ask!
You want to write a loop which loops through numbers 1 to (Inputted Number). And if you found a factor, you print it and divide the input by the factor. (And test if it can be divided again by the same number), else then skip to the next number.
Keep doing this until your input divides down to 1.
This program will break the number down to prime factors:
public class Factor {
public static void main() {
//Declares Variables
int factor = 15;
int i = 2;
System.out.println("Listing Factors:\n");
while (factor>1) {
//Tests if 'i' is a factor of 'factor'
if (factor%i == 0) {
//Prints out and divides factor
System.out.println(i);
factor = factor/i;
} else {
//Skips to next Number
i++;
}
}
}
}
Output:
Listing Factors:
3
5

Categories