I'm trying to sum all primes up to a number.
First I removed all evens and pushed the rest to an odd-only array.
Then I'm going over the array and splicing all the numbers that divide by other numbers but 1 and themselves, and replacing them with zero.
Everything seemed to go okay, however, notice in my first console.log that the last element is 977 (which is the num passed).
A line later I forEach the array and print all numbers over 970 but 977 isn't there.
Any ideas on how this happened? (I ruled out voodoo..)
function sumPrimes(num) {
var arr = [2];
for (var i = 3; i <= num; i++) {
if (i % 2 !== 0) {
arr.push(i);
}
}
console.log(arr);
arr.forEach(function(x) {
if(x > 970){
console.log(x);
}
if (x > 3) {
for (var j = 3; j < x; j += 2) {
if (x % j == 0) {
arr.splice(arr.indexOf(x), 1, 0);
}
}
}
})
// console.log(arr);
var res = arr.reduce(function(acc, val) {
return acc + val;
}, 0)
console.log(res);
}
sumPrimes(977);
The issue is how you're manipulating the array and the array never actually ends up containing 977.
What happens is you find a non-prime and alter the array in place so that it's now 0 but you continue to run checks on that prime.
This causes any following indexOf lookup for that value to return -1 and hence you get unexpected results.
if (x % j == 0) {
arr.splice(arr.indexOf(x), 1, 0); // This won't work after the first assign to 0
}
You can easily fix this by inserting a 'break;' immediately following the splice to short circuit the loop, however you can easily simplify & dramatically speed this up using the index parameter available in a forEach to remove the array position lookup entirely.
function sumPrimes(num) {
var arr = [2];
for (var i = 3; i <= num; i++) {
if (i % 2 !== 0) {
arr.push(i);
}
}
console.log(arr);
arr.forEach(function(x, idx) {
if(x > 970){
console.log(x);
}
if (x > 3) {
for (var j = 3; j < x; j += 2) {
if (x % j == 0) {
arr[idx] = 0;
break;
}
}
}
})
// console.log(arr);
var res = arr.reduce(function(acc, val) {
return acc + val;
}, 0)
console.log(res);
}
sumPrimes(977);
EDIT: If anyone wants a simple, more efficient method of determining whether a number is prime or not, I suggest using the Trial Division method, not the one above.
You can find a succinct, well tested example on Rosetta code:
function isPrime(n) {
if (n == 2 || n == 3 || n == 5 || n == 7) {
return true;
} else if ((n < 2) || (n % 2 == 0)) {
return false;
} else {
for (var i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i == 0)
return false;
}
return true;
}
}
console.log(isPrime(977));