200万以下所有素数的总和

时间:2019-07-13 17:10:47

标签: javascript

此代码放置了以下所有素数为200万的素数并计算它们的总和,我不认为素数是错误的,但我收到的总和为143010484903,但正确答案是142913828922

有人可以帮我怎么回事吗?我是JS的新手。

- service:
    name: apache
    state: started
    enabled: yes

3 个答案:

答案 0 :(得分:1)

我认为您确实有一些大于2000000的质数,因为您是在计算平方根后对值进行底数计算。尝试改用.ceil()。您甚至可以使用较小的值进行测试,尝试采用10console.log(primes);,您会发现还有额外的价值11示例[2, 3, 5, 7, 11];

let sqrtNum = Math.ceil(Math.sqrt(num));

答案 1 :(得分:1)

我不确定代码中的错误是什么,但是在内部循环的某个地方,您会陷入困境。您的primes.length也比我的代码长。

let primes = [2];

mainLoop: for (let num = 3; num < 2000000; num += 2) {
  let sqrtNum = Math.floor(Math.sqrt(num));
  for (let i = 0; primes[i] <= sqrtNum; i++) {
    if (num % primes[i] == 0) {
      continue mainLoop;
    }
  }
  primes.push(num);
}

let sum = 0;
for (let i = 0; primes[i] < 2000000; i++) {
  sum += primes[i];
}

console.log(sum);

和带有筛子的快速版本

var sieve = Array(2000000).fill(false);
var primes = [2];

for(let i=0; i<sieve.length; i+=2) sieve[i] = true;

for(var i=3; i < sieve.length; i+=2){
  if(sieve[i]) continue;
  primes.push(i);
  for(let j=i*i; j<sieve.length; j+=i+i){
    sieve[j] = true;
  }
}

console.log(primes.reduce((a,b) => a+b));

答案 2 :(得分:1)

您的算法正在将合成添加到素数列表中

let num = 3;
let primes = [2];

while (num < 123) {
  let sqrtNum = Math.floor(Math.sqrt(num));
  for (i = 0; sqrtNum >= primes[i]; i++) {
    if (num % primes[i] == 0) {
      num += 2;
      i = 0;
    } else {
      continue;
    }
  }
  primes.push(num);
  num += 2;
}
console.log(...primes)

上述列表中的第121号通知(11 x 11)。

问题出在while循环的逻辑以及管理变量num的方式上。考虑一下在测试复合值时会发生什么。115您将进入循环n = 115的部分:

  let sqrtNum = Math.floor(Math.sqrt(num));  // sqrtNum == 10
  for (i = 0; sqrtNum >= primes[i]; i++) {   // testing against [2, 3, 5, 7, 9]
    if (num % primes[i] == 0) {              // on the 3rd loop you find 115
      num += 2;                              // is divisible by 5 and increase
      i = 0;                                 // nums to 117,and find it's composite
                                             // eventually nums is 121 but you haven't changed
    } else {                                 // sqrtNum to refect you now need to search
      continue;                              // up to 11 so you think 121 is prime
    }
  }
  primes.push(num);
  num += 2;
}

这种情况很少发生,这就是为什么您的总和接近的原因。更改为math.ceil似乎可以解决此问题,因为ceil(Math.sqrt(115))为11,但是我不确定您如何证明这总是正确的。

一个更好的主意是将筛子张贴在另一个答案中。但这是一个贴近您代码但可以管理num的修复程序,因此您无需重新计算num就不会增加sqrtNum

let num = 3;
let primes =[2];

while(num <= 130) {
  let composite = false
  let sqrtNum = Math.floor(Math.sqrt(num)); // sqrtNum will be calculated for each change of num
  for(i = 0; sqrtNum >= primes[i]; i++) {
    if(num % primes[i] == 0) {
      composite = true
      break
    } 
  }
  if (!composite){
    primes.push(num);
  }
  num += 2
}
// no 121!
console.log(...primes);