8

I read lot many algorithms to find prime numbers and the conclusion is that a number is a prime number if it is not divisible by any of its preceding prime numbers.

I am not able to find a more precise definition. Based on this I have written a code and it performs satisfactory till the max number I pass is 1000000. But I believe there are much faster algorithms to find all primes lesser than a given number.

Following is my code, can I have a better version of the same?

 public static void main(String[] args) {
    for (int i = 2; i < 100000; i++) {
        if (checkMod(i)) {
            primes.add(i);
        }
    }
}

private static boolean checkMod( int num) {
    for (int i : primes){
        if( num % i == 0){
            return false;
        }
    }
    return true;
}
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
dharam
  • 7,882
  • 15
  • 65
  • 93
  • Have you tried searching the site? There are a ton of questions on prime number finding algorithms. – Wooble May 21 '12 at 18:48
  • yes I found a solution here http://stackoverflow.com/questions/3808171/fast-algorithm-for-finding-prime-numbers But somewhere it is not well explained and I believe its complicated :( – dharam May 21 '12 at 18:50
  • http://codereview.stackexchange.com/ – j08691 May 21 '12 at 18:59

7 Answers7

21

The good thing in your primality test is that you only divide by primes.

private static boolean checkMod( int num) {
    for (int i : primes){
        if( num % i == 0){
            return false;
        }
    }
    return true;
}

The bad thing is that you divide by all primes found so far, that is, all primes smaller than the candidate. That means that for the largest prime below one million, 999983, you divide by 78497 primes to find out that this number is a prime. That's a lot of work. So much, in fact, that the work spent on primes in this algorithm accounts for about 99.9% of all work when going to one million, a larger part for higher limits. And that algorithm is nearly quadratic, to find the primes to n in this way, you need to perform about

n² / (2*(log n)²)

divisions.

A simple improvement is to stop the division earlier. Let n be a composite number (i.e. a number greter than 1 that has divisors other than 1 and n), and let d be a divisor of n.

Now, d being a divisor of n means that n/d is an integer, and also a divisor of n: n/(n/d) = d. So we can naturally group the divisors of n into pairs, each divisor d gives rise to the pair (d, n/d).

For such a pair, there are two possibilities:

  1. d = n/d, which means n = d², or d = √n.
  2. The two are different, then one of them is smaller than the other, say d < n/d. But that immediately translates to d² < n or d < √n.

So, either way, each pair of divisors contains (at least) one not exceeding √n, hence, if n is a composite number, its smallest divisor (other than 1) does not exceed √n.

So we can stop the trial division when we've reached √n:

private static boolean checkMod( int num) {
    for (int i : primes){
        if (i*i > n){
            // We have not found a divisor less than √n, so it's a prime
            return true;
        }
        if( num % i == 0){
            return false;
        }
    }
    return true;
}

Note: That depends on the list of primes being iterated in ascending order. If that is not guaranteed by the language, you have to use a different method, iterate by index through an ArrayList or something like that.

Stopping the trial division at the square root of the candidate, for the largest prime below one million, 999983, we now only need to divide it by the 168 primes below 1000. That's a lot less work than previously. Stopping the trial division at the square root, and dividing only by primes, is as good as trial division can possibly get and requires about

2*n^1.5 / (3*(log n)²)

divisions, for n = 1000000, that's a factor of about 750, not bad, is it?

But that's still not very efficient, the most efficient methods to find all primes below n are sieves. Simple to implement is the classical Sieve of Eratosthenes. That finds the primes below n in O(n*log log n) operations, with some enhancements (eliminating multiples of several small primes from consideration in advance), its complexity can be reduced to O(n) operations. A relatively new sieve with better asymptotic behaviour is the Sieve of Atkin, which finds the primes to n in O(n) operations, or with the enhancement of eliminating the multiples of some small primes, in O(n/log log n) operations. The Sieve of Atkin is more complicated to implement, so it's likely that a good implementation of a Sieve of Eratosthenes performs better than a naive implementation of a Sieve of Atkin. For implementations of like optimisation levels, the performance difference is small unless the limit becomes large (larger than 1010; and it's not uncommon that in practice, a Sieve of Eratosthenes scales better than a Sieve of Atkin beyond that, due to better memory access patterns). So I would recommend beginning with a Sieve of Eratosthenes, and only when its performance isn't satisfactory despite honest efforts at optimisation, delve into the Sieve of Atkin. Or, if you don't want to implement it yourself, find a good implementation somebody else has already seriously tuned.

I have gone into a bit more detail in an answer with a slightly different setting, where the problem was finding the n-th prime. Some implementations of more-or-less efficient methods are linked from that answer, in particular one or two usable (though not much optimised) implementations of a Sieve of Eratosthenes.

Community
  • 1
  • 1
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
1

I always use Eratosthenes sieve:

isPrime[100001] // - initially contains only '1' values (1,1,1 ... 1)
isPrime[0] = isPrime[1] = 0 // 0 and 1 are not prime numbers

primes.push(2); //first prime number. 2 is a special prime number because is the only even prime number.
for (i = 2; i * 2 <= 100000; i++) isPrime[i * 2] = 0 // remove all multiples of 2

for (i = 3; i <= 100000; i += 2) // check all odd numbers from 2 to 100000
    if (isPrime[i]) {
        primes.push(i); // add the new prime number to the solution
        for (j = 2; i * j <= 100000; j++) isPrime[i * j] = 0; // remove all i's multiples
    }

return primes

I hope you understand my comments

gabitzish
  • 9,535
  • 7
  • 44
  • 65
0

I understand a prime number to be a number that is only divisible by itself and the number 1 (with no remainder). See Wikipedia Article

That being said, I don't understand the algorithm very well in the second comment but one small improvement to your algorithm would be to change your for loop to:

for (int i = 5; i < 100000; i = i + 2) {
    if (checkMod(i)) {
        primes.add(i);
    }
}

This is based on the assumption that 1, 2, and 3 are all prime numbers and all even numbers thereafter are not prime numbers. This at least cuts your algorithm in half.

Benjamin Oman
  • 1,654
  • 1
  • 17
  • 19
  • 3
    No, that has almost no impact at all. Finding the composites non-prime is the cheap part of trial division. The expensive part is checking the primes. Oh, and **1 is not a prime**. – Daniel Fischer May 21 '12 at 22:02
0

I want to make a still slightly improved version to the 0ne suggested by Benjamin Oman above, This is just one modification to avoid checking for primality of all the numbers ending with digit '5', because these numbers are certainly not primes as these are divisible by 5.

for (int i = 7;(i < 100000) && (!i%5==0); i = i + 2) {
    if (checkMod(i)) {
        primes.add(i);
    }
}

This is based on the assumption that 2,3,5 are primes. The above little change will reduce all factors of 5 and improve.

0

Nicely explained by @Daniel Fischer.

A Implementation in C++ from his explanation:

#include<iostream>

using namespace std;

long* getListOfPrimeNumbers (long total)
{
  long * primes;
  primes = new long[total];
  int count = 1;
  primes[0] = 2;
  primes[1] = 3;
  while (count < total)
  {
    long composite_number = primes[count] + 2;
    bool is_prime = false;
    while (is_prime == false)
    {
      is_prime = true;
      for (int i = 0; i <= count; i++)
      {
        long prime = primes[i];
        if (prime * prime > composite_number)
        {
          break;
        }
        if (composite_number % prime == 0)
        {
          is_prime = false;
          break;
      }
      }
      if (is_prime == true)
      {
        count++;
        primes[count] = composite_number;
      }
      else
      {
        composite_number += 2;
    }
  }
  }
  return primes;
}

int main()
{
  long * primes;
  int total = 10;
  primes = getListOfPrimeNumbers(total);
  for (int i = 0; i < total; i++){
    cout << primes[i] << "\n";
  }
  return 0;
}
Community
  • 1
  • 1
Love Sharma
  • 1,981
  • 1
  • 18
  • 37
0
import array , math

print("enter a range to find prime numbers")

a= 0
b= 5000
c=0
x=0
k=1
g=[2]
l=0


for I in range( a , b):
    for k in g:
        x=x+1


        if k>2:
            if k > math . sqrt( I ):

                break

        if( I % k==0):

            c=c+1
            break
    if c==0:
        if I!=1:

            g . append( I )



    c=0    
print g



#this algorithm will take only 19600 iteration for a range from 1-5000,which is one of fastest algorithm according to me
0

I found the mathematicians say 'that' "prime numbers after 3 are always one side of the multiple of 6". It maen 5 ,7 prime numbers is nearer to 6. 11,13 are also nearer to 62. 17,19 also 63. 21,23 also 6*4. I wrote both normally and like this up to 1million, I found this algorithm is also right and more quickly.


num=1000000
prime=[2,3]
def test(i):
    for j in prime:
        if(i%j==0):
            break
        if(j*j>i):
            prime.append(i)
            break
    return 0
for i in range (6,num,6):
    i=i-1
    test(i)
    i=i+2
    test(i)
    i=i-1
    
print(prime)
  • why not go for multiples of 15? and compare 8 differences (+/- 2,4,6,14) vs. multiple of 6 up to 30 (+/-2 * 4.5) = 9 differences? why stop there? – iAmOren Jul 12 '20 at 05:04
  • Sorry, I can't catch what you mean. May be my English problem , please explain me more ditial Sir. – Aye Chan Ko Jul 14 '20 at 02:10
  • Using 6 +/- 1 is a complication. Best to start with 2, then from 3 +2 (3, 5, 7, 9...) and check against already found primes. In javascript: `function primesUpTo(max) { var primes=[2]; for(i=3; i<=max; i+=2) { var prime=true; for(j=0; j – iAmOren Jul 14 '20 at 05:50