- Adding 1 2 3 to the prime list initially
Actually, just 2 is sufficient. Hard-coding 3 might save, at most, a millisecond. There's no need to harp on 1. I am convinced that including it was an honest mistake. You already knew, and working on this program would have helped confirm this.
- Calculating the last digit of the number to be checked
The last digit? In what base? Base 10? I think this might be your problem.
- Checking if the digit is 0, 2 or 4 or 6 or 8 then skipping the number
else calculating the square root of the number
I think this is where the problem lies. Your program should simply skip even numbers, because, aside from −2 and 2, they're all composite. On the other hand, this won't halve running time because odd numbers like 91 and and 2209 might require more effort to be ruled out as not prime.
- Trying to Divide the number starting from 2 till the square root of the number
if number is divisible then skipping the number else adding it to the prime list
Does "2 till the square root of the number" include numbers like 4, 6 and 9? The only potential factors that need to be checked are numbers that have already been proven prime. If n is not divisible by 7, it won't be divisible by 49 either. If you're building up a list, you might as well use it to check potential primes.
Benchmarking Java's a little difficult because you're at the mercy of the runtime system. Still, a minute and a half, while it would have been considered miraculous by Mersenne, is too slow today. Five, ten seconds, that I'd find acceptable.
Maybe this is one of those cases where you should avoid the use of objects in favor of an array of primitives. My first draft took even longer than yours. Eventually I came up with this:
static int[] fillWithPrimes(int quantity) {
int[] primes = new int[quantity];
primes[0] = 2;
int currPi = 1;
int currIndex = 0;
int currNum = 3;
int currPrime;
boolean coPrimeFlag;
double squareRoot;
while (currPi < quantity) {
squareRoot = Math.sqrt(currNum);
do {
currPrime = primes[currIndex];
coPrimeFlag = (currNum % currPrime != 0);
currIndex++;
} while (coPrimeFlag && currPrime <= squareRoot);
if (coPrimeFlag) {
primes[currPi] = currNum;
currPi++;
}
currNum += 2;
currIndex = 0;
}
return primes;
}
Then I wrote a main()
that notes the time before calling fillWithPrimes()
with a quantity
parameter of 1,000,000, and reports on the results:
run:
Operation took 2378 milliseconds
10th prime is 29
100th prime is 541
1000th prime is 7919
10000th prime is 104729
100000th prime is 1299709
1000000th prime is 15485863
BUILD SUCCESSFUL (total time: 2 seconds)
I'm sure it can be optimized further. Me, personally, I'm satisfied with two and a half seconds.