我试图解决项目euler 10问题(找到所有素数的总和低于200万),但代码需要永远完成,我如何让它更快?
console.log("Starting...")
var primes = [1000];
var x = 0;
var n = 0;
var i = 2;
var b = 0;
var sum = 0;
for (i; i < 2000000; i++) {
x = 0;
if (i === 2) {
primes[b] = i
sum += primes[b];
console.log(primes[b]);
b++;
}
for (n = i - 1; n > 1; n--) {
if (i % n === 0) {
x++;
}
if (n === 2 && x === 0) {
primes[b] = i;
sum += primes[b];
console.log(primes[b]);
b++;
}
}
}
console.log(sum)
答案 0 :(得分:5)
你可以做的最大超级简单的事情,以加快速度:
找到除数时突破内循环!
当你检查素性时,先从小除数开始,而不是从大除数开始。您可以更快地找到复合材料。
您只需要检查除数&lt; = Math.sqrt(n)
您只需要检查素数除数。你有一份清单。
循环外的进程2,然后只在循环中执行奇数:for(i=3;i<2000000;i+=2)
答案 1 :(得分:0)
因为无论如何你都保留了一个素数数组,你可以分两步分割这个过程:
正如其他人所指出的那样,你只需要检查一个候选人数是否可以被另一个不大于候选人平方根的素数分割。如果你可以写一个数字作为素数的乘积,那么其中一个素数总是低于或等于数字的平方根。
此代码可以进一步优化,但比初始版本快几个数量级:
function primesUpTo(limit) {
if (limit < 2) return [];
var sqrt = Math.floor(Math.sqrt(limit));
var testPrimes = primesUpTo(sqrt);
var result = [].concat(testPrimes);
for (var i=sqrt+1 ; i<=limit ; i++) {
if (testPrimes.every(function(x) { return (i % x) > 0 })) {
result.push(i);
}
}
return result;
}
var primes = primesUpTo(2000000);
var sum = primes.reduce(function(acc, e) { return acc + e });
答案 2 :(得分:0)
这是另一个基于Sieve of Eratosthenes的版本。它需要更多的内存,但如果这与你无关,它也会非常快。
// just a helper to create integer arrays
function range(from, to) {
var numbers = [];
for (var i=from ; i<=to ; i++) {
numbers.push(i);
}
return numbers;
}
function primesUpTo(limit) {
if (limit < 2) return [];
var sqrt = Math.floor(Math.sqrt(limit));
var testPrimes = primesUpTo(sqrt);
var numbers = range(sqrt+1, limit);
testPrimes.forEach(function(p) {
numbers = numbers.filter(function(x) { return x % p > 0 });
});
return testPrimes.concat(numbers);
}
var primes = primesUpTo(2000000);
var sum = primes.reduce(function(acc, e) { return acc + e });