### Betlista's blog

By Betlista, 10 years ago,

It is easy to find if some number (say N) is prime or not — you simply need to check if at least one number from numbers lower or equal sqrt(n) is divisor of N. This can be achieved by simple code:

boolean isPrime( int n ) {
if ( n == 1 ) return false; // by definition, 1 is not prime number
if ( n == 2 ) return true; // the only one even prime
for ( int i = 2; i * i <= n; ++i )
if ( n%i == 0 ) return false;
return true;
}


So it takes sqrt(n) steps to check this. Of course you do not need to check all even numbers, so it can be "optimized" a bit:

boolean isPrime( int n ) {
if ( n == 1 ) return false; // by definition, 1 is not prime number
if ( n == 2 ) return true; // the only one even prime
if ( n%2 == 0 ) return false; // check if is even
for ( int i = 3; i * i <= n; i += 2 ) // for each odd number
if ( n%i == 0 ) return false;
return true;
}


So let say that it takes 0,5*sqrt(n) steps. That means it takes 500.000.000 steps to check that 1.000.000.007 is a prime.

But there is great idea — why to "do not check even numbers". This idea can be extended to: "do not divide N by candidate numbers, but mark the prime multiples as 'not prime'".

In other words: if we know about some number p, taht it is prime, we mark all multiples (2*p, 3*p, 4*p, ...) as not a prime. To implement this we need limit (max number we care about), let say it is 120 (because there is nice animation of algorithm on wikipedia).

In Java I'm using this code:

    private static final boolean[] isPrime = new boolean[121];
static {
Arrays.fill( isPrime, true ); // first we assume all numbers are primes if not shown otherwise
isPrime[ 0 ] = false; // zero is not prime - it'is not greater than 1
isPrime[ 1 ] = false; // one is not prime - it'is not greater than 1
for ( int p = 2; p < isPrime.length; ++p ) {
if ( isPrime[ p ] ) {
for ( int m = 2; m * p < 121; ++m ) {
isPrime[ m * p ] = false;
}
}
}
}


Now, you can answer the question "is n prime" in constant time. Of course problems like this one are so simple, that you won't see it as problems, but it is subproblem of some more diffucult problem often.

You can memorize the primes too. And while it holds that even number multiply by whatever is even (and there is just one even prime number), you can skip all even m:

    private static final int LIMIT = 121;
private static final boolean[] isPrime = new boolean[LIMIT + 1];
private static ArrayList<Integer> primes = new ArrayList<Integer>();
static {
Arrays.fill( isPrime, true ); // first we assume all numbers are primes if not shown otherwise
isPrime[ 0 ] = false; // zero is not prime - it'is not greater than 1
isPrime[ 1 ] = false; // one is not prime - it'is not greater than 1
isPrime[ 2 ] = true; // only one even prime
for ( int i = 4; i <= LIMIT; i += 2 ) {
isPrime[ i ] = false;
}
for ( int p = 3; p <= LIMIT; p += 2 ) {
if ( isPrime[ p ] ) {
for ( int m = 3; m * p < LIMIT; m += 2 ) {
isPrime[ m * p ] = false;
}
}
}
}


Maybe you would like to have primes in array instead of List — you can use toArray(int []) method or you find out how many prime numbers (lower than limit) there are. That's why I'm adding this table here:

limit # of primes last lower prime first greater prime
120 30 113 (30th) 127 (31st)
1.000 168 997 1009
10.000 1229 9973 10007
100.000 9592 99991 100003
1.000.000 78489 999983 1000003
10.000.000 664579 9999991 10000019
100.000.000 5761455 99999989 100000007

There exist other sieves, also there are other optimizations possible (for example isPrime array do not need to contain even numbers).

Problems where you cen practise:

• 0

 » 10 years ago, # |   -24 Instead of taking the trouble of writing so much you could have just given the link. Here's LightOJ tutorial about the sieve ->LINKAnyways +1 for your efforts :-)
•  » » 10 years ago, # ^ |   +24 Who will read this at LightOJ? One can't read anything here without registration, and this is really weird.
 » 10 years ago, # |   +1 A small and common mistake.The limit in Sieve of Eratosthenes is square root of N in the first for, not N. int lim=(int)Math.sqrt(LIMIT)+1; for ( int p = 3; p <=lim; p += 2 ) { if ( isPrime[ p ] ) { primes.add( p ); for ( int m = 3; m * p < LIMIT; m += 2 ) { isPrime[ m * p ] = false; } } 
•  » » 10 years ago, # ^ | ← Rev. 2 →   +2 another "mistake", or optimization for ( int m = 3; => for ( int m = p;
•  » » 10 years ago, # ^ | ← Rev. 2 →   0 Thanks, idea is correct, for marking primes in isPrime array this approach is correct, but in this implementation primes list does NOT contain primes greater than sqrt(LIMIT) + 1. It is required to iterate over the array from lim to LIMIT for addition of all primes.
 » 10 years ago, # |   0 Thanks for the practice problems.
 » 9 years ago, # |   0 I wrote an article about this in my blog. The article is in spanish. http://prodeportiva.wordpress.com/2013/02/11/criba-de-eratostenes/
 » 9 years ago, # |   0 There exists a better version of sieve whose runtime is linear, here's the tutorial (translated to English using google translator). You can make it faster and cache friendly using some bitwise tricks (check the following link).There is also another variant of sieve which is known as segmented sieve.Thanks :)
•  » » 8 years ago, # ^ | ← Rev. 17 →   +3 You can also optimize the sieve further by starting at the number the first for-loop is at, so start at 3*3, then 5*5, 7*7 because 5*3 has already been taken care of by the 3's and 7*3 and 7*5 has already been declared not prime by the 5 and 3.It is a small optimization, but can possibly speed up the process a you get to larger values nE: Note this works accurately only for languages for with an arbitrary precision library, otherwise, because of c/c++ lack of large integer types, this tends to not work very wellE2: Nvm, If you use unsigned long long, it should workWith Optimization: \$ time ./auto Primes below 100000000 is 5761455 real 0m5.435s user 0m5.332s sys 0m0.068s Without time ./auto Primes below 100000000 is 5761455 real 0m10.143s user 0m10.045s sys 0m0.056s As you can see, time difference is very apparent the larger the values you are looking for and all it took was one variable change to get these faster results :D
 » 3 years ago, # |   0 One more basic problem related to primes which can be added. https://www.spoj.com/problems/PRIME1/
 » 4 months ago, # |   -18 Thanks for the problem set in the end. The last one was a nice problem 109B CollidersAlso, there is another concept called segmented sieve a sort of modification to the basic one. It's a memory-efficient algorithm to compute primes between two large numbers.These GFG videos explained great!