Is “sieve” a variable that javascript natively understands?
No, “sieve” is just a variable name. We could have called it “elephantPajamas”. The author chose that name as a reference to the Sieve of Eratosthenes, the algorithm developed by Erantosthenes in 3rd century BC Greece.
From the way the code is written, it looks like sieve is defined as an array, but then nothing else is done with that variable until the code checks if the array index is false, and then pushes the prime number to the primes array. But it doesn’t look like there should be any way for it to know.
Yes, the way sieve is used is a bit odd. It is declared but never initialized. So, how does an uninitialized element in an array evaluate in JS? Let’s test it:
var myArray = [];
console.log(myArray[3]);
// -> undefined
if (myArray[3])
console.log("JS evaluated 'undefined' as 'true'!");
else
console.log("JS evaluated 'undefined' as 'false'!");
// -> JS evaluated 'undefined' as 'false'!
Aha! So, sieve is an array that is never initialized so every index in it evaluates as false. This is what the algorithm uses. Perhaps a better name for that array would be hasBeenMarkedAsNotPrime because that is how the logic is working. It starts out assuming that every number is prime (undefined). As we do our i loop, we will check if an index has not been flipped to “true” (true == not prime) - if it has not then it is prime.
In the for loop, first we check if (!sieve[i]) {
, or we’re checking if that index has been marked true yet. It hasn’t of course because we start at 2 and nothing in sieve has been marked true. So, that means that it’s prime (this assumes - accurately - that we are starting with a prime - this would fail if we started at 4) and we add that to our primes array. Then we index through all the multiples of i and mark them as true (in other words, “not prime”):
for (j = i << 1; j <= max; j += i) { // remember i << 1 is the same as i*2, starting at the next multiple
sieve[j] = true;
}
So, this will let us know about any non-primes above us. This is where sieve is getting set. It is a little odd that we’re setting up sieve on the fly, but it works because we’re working from the bottom up and sieve is always one step ahead of the number that we’re checking. When we get to 3, sieve[3] is still undefined so we know that 3 is prime. When we get to sieve[4], that is true (marked when we looped through the multiples of 2) so we know that that is not prime. (We don’t need to loop through the multiples of 4 since we already got all of those as multiples of 2). sieve[5] is undefined so that is prime. sieve[6] is true (we got that as a multiple of 2 and then again for 3) so we know that it is not prime, etc, etc.
If the algorithm itself is confusing you, then please go to that wiki and see that gif they have. Perhaps even make a grid on a piece of paper and try it yourself. It’s a strange little algorithm, but it’s ingenious. Hopefully with an understanding of the wacky way sieve is being used, this is falling into place.
Don’t feel bad - I’m pretty good at algorithms and this one took me a couple looks, especially how sieve is being used. That wouldn’t work in many programming languages. But it works in JS.