This one was really tricky, and I had a feeling that there was an actual algorithm that this one was based on. There was! It’s called the Sieve of Eratosthenes. What is the Sieve of Eratosthenes? It’s an ancient algorithm for finding all prime numbers up to any given limit. That’s exactly part of what I am supposed to do here.

Again, first I took a look at the provided arguments and expected outcomes. They would at least partially tell me how I should approach the algorithm. Since the second expected outcome was going to be fairly massive, I focused on the first.

Before doing anything, I had to figure out what my algorithm was supposed to achieve:

The solution should sum all the prime numbers up to and including the provided argument. However, it has to take into consideration that the provided argument might not be a prime.

The solution had to check whether or not a number was a prime or not. This meant conditional statements, and some form of looping.

Once all the primes were found, they had to be summed up into one number which would then be returned.

Not only was I provided with a refresher about prime numbers in the Sieve of Eratosthenes, but it was also included on the algorithm page. I started very simple. I decided that since some kind of filtering and reduction was going to be involved, that I should use array(s). I also figured that I should use a for loop, and that there probably should be more than one counter. That’s because I had to differentiate between prime and non prime numbers. That also meant that there would be more than one for loop. Probably two. So probably two for loops, two counters, and two arrays.

This is what I initially came up with:

JavaScript

1

2

3

4

5

6

7

8

9

10

functionsumPrimes(num){

varprimes=[],

filteredArr=[],

i,

j;

for(i=2;i<=num;i++1){}

}

I declared two variables, one called primes for the prime numbers, and one called filteredArr for everything else. I assigned each an empty array. i and j are counters. I began i at 2, because 2 is the first prime number. 1 is not because it is only divisible by itself, whereas a prime number is divisible by itself and by 1. But this was hard, and it involved a lot of research. I also had to revisit for loops, and especially nested for loops.

The next thing I knew for sure, was that I would have to somehow push the prime numbers into the empty primes array. So this is what I did next:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

functionsumPrimes(num){

varprimes=[],

filteredArr=[],

i,

j;

for(i=2;i<=num;i++){

primes.push(i);

}

}

This in of itself did nothing. sumPrimes(10) returned undefined. Of course. Most basically, nothing was being returned. If I did this:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

functionsumPrimes(num){

varprimes=[],

filteredArr=[],

i,

j;

for(i=2;i<=num;i++){

primes.push(i);

}

returnprimes;

}

sumPrimes(10);

[

2,

3,

4,

5,

6,

7,

8,

9,

10

]

All numbers except 1 are returned. So I had to start doing some prime checking and non-prime “filtering”. This is where things got hairy. If a number was NOT a non-prime, and therefore a prime, it would get pushed into the primes array.

How was I going to check whether or not a number was a prime or not a prime and that the prime number would be pushed into the primes array? Lots of research, re-reading of the Sieve of Eratosthenes algorithm and pseudo code!

I finally came across a piece of code that contributed towards checking for non-prime numbers, and learned something new. The left shift bitwise operator. An example:

JavaScript

1

2

3

j=2<<1;

returns4

<< being the left shift bitwise operator. The left shift bitwise operator doubles the number to the left of it, and the number one always appears to the right. In other words, j = 2 * 2;

To better understand this, let’s also examine the right shift bitwise operator:

JavaScript

1

2

3

j=4>>1;

returns2;

Another way of looking at the left shift bitwise operator is that it results in the multiple of the number to the left of the operator. In the case of 5, it results in 10. In the case of 4, it results in 8. In the case of 2, it results in 4.

Another way of looking at the right shift bitwise operator is that it results in the multiple of 2 that equals the number to the left of the right shift bitwise operator. Here the multiple of 2 that results in 4 is 2. But what if I did this:

So based on this information, how was I going to apply it to separating prime numbers from non-prime numbers and then return only the sum of all the prime numbers up to num? This is where for loops, nested for loops, if statements, and booleans would come into play. With the help of StackOverflow and a bit of hindsight, I came across the solution:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

functionsumPrimes(num){

varprimes=[],

filteredArr=[],

i,

j;

for(i=2;i<=num;i++){

if(!filteredArr[i]){

primes.push(i);

// j = i << 1; is same as multiples of i and j = i. So the number that is passed over

// in the inside loop is the prime number. And that refers back to !filteredArr[i].

for(j=i<<1;j<=num;j+=i){

filteredArr[j]=true;

}

}

}

returnprimes.reduce(function(a,b){

returna+b;

});

}

sumPrimes(10);

Now let’s break this down to all its components to see how everything works:

I already have explained why I created two arrays and two counters, and we will revisit them a bit later. Next to tackle is the for loops. Since I first wrote this algorithm, I’ve been getting better at grasping the concept of nested for loops. Here, for example, for every iteration of the outer for loop, the inner for loop iterates through its whole range of numbers. In other words, the outer for loop, which is dealing with adding prime numbers to the primes array, is dependent on the inner for loop to determine which numbers are not primes. This is similar in concept to the example of the Sieve of Eratosthenes in the Wikipedia article I share here entitled Sieve of Eratosthenes.

In the first for loop, I have i = 2; because 2 is the first natural prime number. i <= num; because the loop has to iterate over all the numbers between the first prime number, i =2, up to and including num. i++ represents the incrementation of i by 1 after the first iteration of the outer for loop. That being said, when i = 2 in the outer for loop, that same value is applied to j = i << 1; in the second for loop. In other words, j = 2 << 1; which means that j = 4 when i is = 2 on the first iteration of the inner for loop. This also means that the second for loop has skipped over i = 2; This is where if(!filteredArr[i]) { primes.push(i); comes in. Since the second for loop, which refers to the filteredArr, and in which j = i << 1, then filteredArr[j] = true. This means that filteredArr[j] is not a prime. Why? Because j = a multiple of 2. It is with if(!filteredArr[i]) { primes.push(i) that a differentiation between prime numbers and non-prime numbers can be achieved, and primes are pushed into the primes array.

But that’s not all. For each iteration of the outer for loop, the inner for loop iterates through the full range of numbers starting with j = i << 1; which is equal to 4. That means that all the multiples of two that result from that iteration coerce to true and are omitted from the primes array. This process continues until there are no more numbers to iterate over. Then the outer for loop goes onto the next iteration, i.e., the second one, where i is now = 3; That means that j = 3 << 1; in other words, j = 6, and i = 3. 3 is skipped over, and is pushed into the primes array. And so on, until num is reached. if num is a prime, it gets pushed into the primes array, but if it is not a prime, it does not.

Finally, all the primes have to be summed up and the total has to be returned. I achieved this by the following:

JavaScript

1

returnprimes.reduce(function(a,b){returna+b;});

This step is fairly straightforward. To recap, the .reduce() method applies a function against an accumulator and each value of the array, from left to right, to reduce it to a single value. All that is returned is that single value, and not an array containing a single element.

Syntax:

JavaScript

1

arr.reduce(callback[,initialValue])

Parameters:

callback: Function to execute on each value in the array. It takes (up to) four arguments:

previousValue: The value previously returned in the last invocation of the callback, or initialValue, if supplied.

currentValue: The current element being processed in the array.

currentIndex: The index of the current element being processed in the array.

array: The array reduce was called upon.

Here, the callback function takes the previousValue/initialValue a, starting at primes[0], “accumulates” it to the next number in the array and so on, until there are no more currentValues to add to the previousValue, and the sum of all the prime numbers in the array is returned in the form of a single number. This is represented by return a + b;

I was a little concerned about the cyclomatic complexity of the solution, and how much of a heap the inner for loop might be accumulating. I will discuss the issue of memory profiling in another post using this algorithm as an example, but I will say this much. The JSHint Metrics for the solution to Sum All Primes is the following:

Not terrible. Not terrible, considering everything that is going on in this relatively little piece of code. The JS heap is between 3.9 and 5.1 mb, or thereabouts. It pretty much stayed the same with subsequent snapshots. I don’t know whether this is fantastic or not yet, since I am still fairly new to memory profiling, but I will address that issue in my post on memory profiling. I should have answers by then! I do know, however, that using arrays to store large amounts of data is definitely the preferred way to go. According to the article Memory Analysis 101 in the Chrome Developer Tools documentation,

Memory can be held by an object in two ways: directly by the object itself, and implicitly by holding references to other objects, and thus preventing them from being automatically disposed by a garbage collector (GC for short).

The size of memory that is held by the object itself is called shallow size. Typical JavaScript objects have some memory reserved for their description and for storing immediate values.

Usually, only arrays and strings can have significant shallow sizes. However, strings often have their main storage in renderer memory, exposing only a small wrapper object on the JavaScript heap.

So much to consider when dealing with the issue of memory in JS development. This is only the tip of the iceburg!

Solution:

Sum All Primes Solution

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

functionsumPrimes(num){

varprimes=[],

filteredArr=[],

i,

j;

for(i=2;i<=num;i++){

if(!filteredArr[i]){

primes.push(i);

// j = i << 1; is same as multiples of i and j = i. So the number that is passed over

// in the inside loop is the prime number. And that refers back to !filteredArr[i].

for(j=i<<1;j<=num;j+=i){

filteredArr[j]=true;

}

}

}

returnprimes.reduce(function(a,b){

returna+b;

});

}

sumPrimes(10);

Solution in ES6:

Sum All Primes Solution in ES6

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

functionsumPrimes(num){

constprimes=[];

constfilteredArr=[];

leti;

letj;

for(i=2;i<=num;i++){

if(!filteredArr[i]){

primes.push(i);

// j = i << 1; is same as multiples of i and j = i. So the number that is passed over

// in the inside loop is the prime number. And that refers back to !filteredArr[i].

Maria Campbell

Founder, Inter-Global Media Network, Inc., where I focus on Front End Development. as well as a digital photographer, videographer, blogger, broadcaster, and graphic designer. Genesis Framework user. I got my start 8+ years ago teaching myself HTML/CSS and Wordpress Development because I couldn't find anyone who could create what I wanted. I have been working with open source software ever since. I am an open source software evangelist, and a "Women in Technology" evangelist. A creative professional myself, I find Web Development to be both practical and creative. I love to cook, travel, read mysteries, love everything French, the beach at sunrise, my three cats, and hope to revisit the city of San Francisco one day.

Reader Interactions

Comment Policy: Your words are your own, so be nice and helpful if you can. Please, only use your real name and limit the amount of links submitted in your comment. We accept clean XHTML in comments, but don't overdo it please. Comments are moderated, so spammy or malicious links will be removed.