Your optimization needs to be applied after getting rid of even number first (except 2).
because when i==2
, you effectively skipped all even numbers by incrementing by i*2
.
Here is a working code:
// prime-3
// sieve implementation
function prime3(n) {
let sieve = (new Array(n)).fill(true);
for (let i = 4; i < n; i+=2) {
sieve[i] = false;
}
// Only iterate up to the square root n for marking
for (let i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
// now it works
// j = j + ( i * 2 )
for (let j = i * i; j <= n; j = j + i*2) {
sieve[j] = false;
}
}
}
return makePrimes(sieve, n);
};
function makePrimes(sieve, n) {
let primes = [];
for (let i = 2; i < n; i++) {
if (sieve[i]) {
primes.push(i);
}
}
return primes;
}
console.log(prime3(100));
Edit
Scratch this. Further testing does show prime3 is 3 times faster then simple sieve.
The code although works, seems put too much tricks to do and introduced both extra calculations and confusion. A simple sieve code like the following in my comparison out performs the one in the answer. Again, KISS is the principle.
It took the script in the origin answer 317ms to sieve 1M numbers, while the simple sieve took only 241ms.
function simpleSieve(n) {
let a = new Array(n)
let answer = []
let p
for (let i = 2; i < n; i ++) {
a[i] = i
}
for (let i = 2; i < n; i++) {
if (a[i]) {
answer.push(a[i])
p = a[i]
for(let j = p; j < n; j += p) {
a[j] = 0
}
}
}
return answer
}
Edit 2
Retested with cpp and prime3 does improve about 3 times faster than simple sieve:
p3:
n = 100000000, t = 866717 microseconds.
n = 200000000, t = 2354425 microseconds.
n = 300000000, t = 3689165 microseconds.
n = 400000000, t = 4950224 microseconds.
n = 500000000, t = 6119779 microseconds.
n = 600000000, t = 7375925 microseconds.
n = 700000000, t = 8647293 microseconds.
n = 800000000, t = 10477116 microseconds.
n = 900000000, t = 11589894 microseconds.
n = 1000000000, t = 12806997 microseconds.
simple:
n = 100000000, t = 2316019 microseconds.
n = 200000000, t = 6063749 microseconds.
n = 300000000, t = 9783295 microseconds.
n = 400000000, t = 13315450 microseconds.
n = 500000000, t = 16640474 microseconds.
n = 600000000, t = 20282461 microseconds.
n = 700000000, t = 24219469 microseconds.
n = 800000000, t = 29203786 microseconds.
n = 900000000, t = 32965856 microseconds.
n = 1000000000, t = 37694084 microseconds.
Codes here for completeness:
void simpleSieve(int n) {
bool *a = (bool *)calloc(n, sizeof(bool));
int p;
memset(a, true, sizeof(bool) * n);
for (int i = 2; i < n; i++) {
if (a[i]) {
p = i;
for (int j = p; j < n; j += p) {
a[j] = 0;
}
}
}
free(a);
}
void prime3(int n) {
bool *sieve = (bool*)calloc(n, sizeof(bool));
sieve[2] = true;
for (int i = 3; i < n; i+=2) {
sieve[i] = true;
}
int step;
for (int i = 2; i * i <= n; i += 1) {
if (sieve[i]) {
step = i*2;
for (int j = i * i; j <= n; j = j + step) {
sieve[j] = false;
}
}
}
free(sieve);
}