I have developed an algorithm for generating prime numbers (which turns out to be an optimized version of the Sieve of Eratosthenes) by reducing the space by a factor of 64.
/*
* Explanation of algorithm
* 1. Avoid storing all the even numbers as they cnt b prime numbers - so divide the size by 2
* 2. Represent each bit of int as a odd number 1,3,5,7 and so on. Each int has 32 bits and will store prime numbers between 0 to 63.
* 3. Again divide the counter by 32, so now the final size of the array would be 32*2=64 (because we are also avoiding even numbers)
* 4. 1st Loop (i)- Loop from i=3 upto squareroot of the given range and increment by 2(because we don't care about the even numbers)
* 5. 2nd Loop (j)- Loop from square of the current number(i) till its less than the counter and increment j by 2*i (Again avoid the even number multiples)
* 6. Mark all the multiples of the j to 1/true.(In our code we set the corresponding bit to 1)
for e:g for setting 9 to be non-prime we simply divide it by 2 and set that bit to 1.
* 7. While printing we check if the bit is set to 0. if yes, then print the number by multiplying (32*[currentIndexInArray]+bit-position)*2 +1.
* Note: it will correctly print all numbers from 3 to given range(should be multiples of 64)
* Even if its not multiple of 64, it still works but wont consider the last 32 numbers in the range.
* Also, it prints 1 in the output and not 2, which probably can be handle by extra conditions.
* its more focused on generating primes above number 3.
*/
public class PrimeNumberOptimized {
static int range = 256;
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
int[] NonPrimeNumbers = new int[(range>>6)+1];
int k=0;
for(int i=3;i*i <= range;i+=2){
//Increment k, everytime i goes beyond int size
if((i>>1)%32==0)
k++;
//Check if it is a prime number, if yes, mark all the bits which are multiples of this number.
if((NonPrimeNumbers[k]&(1<<(i>>1)))==0)
{
for(int j=i*i;j <= range;j+=2*i){// increment j by 2*i, for :eg if i=5, then mark directly 15 skipping 10 as every alternate multiple will be an even number
//set the bit to 1. if i=3 and j=9, then we go to the 1st index in array and set the 9/2th bit in array value.
NonPrimeNumbers[j>>6]|=1<<(j>>1);
}
}
}
int primeCnt = 0;
range >>= 6; // Divide the range by 64 as we need to iterate through the array which is reduced by factor of 64.
for(int arrayIndex=0;arrayIndex < range;arrayIndex++){
for(int bitPosition=0;bitPosition<32;bitPosition++) // Go through each bit of the array value
{
if((NonPrimeNumbers[arrayIndex]&(1<<bitPosition))==0) // check if the current bit is set to 0, if yes, then it represent prime number.
{
System.out.println(((32*arrayIndex+bitPosition)*2)+1); // multiply by 32 to get the correct index in array, add the bitPosition to it and multiply by 2(again we are avoiding even numbers)
primeCnt++;
}
}
}
System.out.println("-Total no of Primes generated->"+(primeCnt));
System.out.println("Total time ="+(System.currentTimeMillis()-startTime));
}
}
Please have a look into this and let me know if it can be optimized any further. Compared with most of the algorithms found online and so far it's quite fast compare to other algorithms.