Sieve of Eratosthenes is a well known prime generation algorithm: link : http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Using the property that all prime numbers essentially fall in the "6k+1" or "6k-1" series, we can reduce the space and time complexity a little bit.
We need to distinguish the composite numbers that occur in "6k+1" and "6k-1" series using an Algorithm.
Concept
To list all prime numbers less than "10" we use the following representation
Approach 1:
square_root(31700)
and is Approach 2:
We change our representation here by mapping each index of the bitset with "k" in "6k+1" or "6k-1" series, which is as follows:
We take two bitsets, one mapping to "6k+1" series and one more mapping to "6k-1" series. If I called these bitsets "u" and "v" respectively:
and
Computing size of the bitset needed !!
This is the maximum value that 'k' can take when I need to map "6k-1" to the number close to 31700 . we compute this as follows:
Case 1: In "6*k+1" series we observe the follows:
series: *7 13 19 25 31 37 43 49 55 61 67 73 79 85 91 97 103 109* ...
Multiples of '7' are distanced '7' units apart from itself, Multiples of '13' are distanced '13' units apart from itself .(units being the numbers in the series) This way we can set multiples of '7' , '13' etc to '0' in the "6k+1" series.
2:We need to mark-out the multiples of '7', '13' etc in the "6k-1" series as well
series: 5 11 17 23 29 35 41 47 53 59 65 71 77 83 89 95 101 107 113 119 ...
we observe the first multiple of '7' occurs at a position 'k1' where k1=7-k, [k-position where '7' occurs i.e in "6k+1" series. ]
similarly,
Once we find 'k1' we can successively mark out the intervals at distance of '7' or '13' respectively from itself in the "6k-1" series to remove their multiples.
Case 2:
In "6k-1" series we need to perform similar operations:
series: *5 11 17 23 29 35 41 47 53 59 65 71 77 83 89 95 101 107 113 119 ...*
Mark-out multiples of '5', '11' etc in "6k-1" series which follow the same principle as above.Multiples of '5' lie at a distance of '5' units from itself as shown in the above series.
We need to mark-out the multiple of '5' in "6k+1" series also.
series: 7 13 19 25 31 37 43 49 55 61 67 73 79 85 91 97 103 109 ...
Mark-out multiples of '5' , '11' etc in "6k-1" series similarly.The first multiple of 5 in "6k+1" series lies at a position k1 where k1=5-k .
[ you can reason this logic easily with a little bit of work around the formula 6k+1 and 6k-1 :)]
Last Step :
We know how to mark-out all the composites , but how much do we need to iterate?
For n=31700 we iterate up to square_root(31700) = 178 Here we need to iterate with k i.e. 6k-1 = 178 => k = (178+1)/6 = 29
Within approximately 30 basic iterations we can generate all prime numbers less than 31700, or infact with fewer basic iterations generate prime numbers less than a fairly large value of 'n'.
Code
#include<iostream>
#include<bitset>
#include<fstream>
#include<ctime>
using namespace std;
int main()
{
bitset<5284> u,l;
u.set();
l.set();
int start= clock();
for(int k=1;k<=29;k++)
{
if(u[k]==1)
{
int m=6*k+1;int n=m-k;
l.set(n,0);
int i=1;
while(k+ i*m <= 5283 && n+ i*m <= 5283 )
{
u.set(k+i*m, 0);
l.set(n+i*m , 0);
i++;
}
if(k+i*m <= 5283)
u.set(k+i*m,0);
if(n+i*m <= 5283)
l.set(n+i*m,0);
}
if(l[k]==1)
{
int m=6*k-1; int n=m-k;
int i=1;
u.set(n,0);
while(k+i*m<= 5283 && n+i*m <= 5283)
{
l.set(k+i*m,0);
u.set(n+i*m,0);
i++;
}
if(k+i*m <= 5283)
l.set(k+i*m,0);
if(n+i*m <= 5283)
u.set(n+i*m,0);
}
}
int stop=clock();
cout<<"time "<<(stop-start)/double(CLOCKS_PER_SEC);
fstream f("p1");
f<<"2\n3\n";
for(int i=1;i<=5283;i++)
{
if(l[i])
f<<6*i-1<<endl;
if(u[i])
f<<6*i+1<<endl;
}
}
//open the file named "p1" to view the list of prime numbers
//hard-coding is used for illustration.