数组中缺少最后一个元素

问题描述 投票:0回答:4

我正在尝试将所有素数相加为一个数字。

首先,我删除了所有偶数,并将其余的推入仅奇数数组。

然后我将检查数组并拼接除 1 和它们本身以外的其他数字的所有数字,并将它们替换为零。

一切似乎都很顺利,但是,请注意我的第一个 console.log 中的最后一个元素是 977(这是通过的数字)。

一行之后,我 forEach 数组并打印所有超过 970 的数字,但 977 不存在。

对于这是如何发生的有什么想法吗? (我排除了巫术..)

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);
javascript arrays primes
4个回答
5
投票

问题在于你如何操作数组,而数组实际上永远不会包含 977。

发生的情况是,您找到一个非素数并更改数组,使其现在为 0,但您继续对该素数运行检查。

这会导致该值的任何后续 indexOf 查找返回 -1,因此您会得到意外的结果。

if (x % j == 0) {
   arr.splice(arr.indexOf(x), 1, 0); // This won't work after the first assign to 0
}

您可以通过插入“break;”轻松解决此问题紧接着拼接以短路循环,但是您可以使用 forEach 中可用的索引参数轻松简化并显着加快速度,以完全删除数组位置查找。

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);


编辑:如果有人想要一种简单、更有效的方法来确定一个数字是否是质数,我建议使用Trial Division方法,而不是上面的方法。

您可以在 Rosetta 代码上找到一个简洁且经过充分测试的示例:

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));


1
投票

戴夫的答案是正确的,但为了这个练习,另一个循环解决方案

        function sumPrimes(num) {

            var prime = [2];
            var isPrime;

            for (var i = 3; i <= num; i++) {

                if (i % 2 !== 0) {
                    isPrime = true;

                    prime.forEach(function (v) {
                        isPrime = isPrime && i % v != 0;
                    });

                    if (isPrime) {
                        prime.push(i);
                    }
                }
            }

            console.log(prime);
            var res = prime.reduce(function (acc, val) {
                return acc + val;
            }, 0)
            console.log(res);
        }

        sumPrimes(977);

0
投票

正如@Dave L 也发现的那样,问题似乎在于:

if (x > 3) {
      for (var j = 3; j < x; j += 2) {
        if (x % j == 0) {
          arr.splice(arr.indexOf(x), 1, 0);
        }
      }
    }
}

当我注释掉它时,977被打印出来,但是当它就位时,我必须尝试使用979让它打印977。你可能从未怀疑过它的原因是因为JavaScript是异步的,所以这实际上是在之前执行的 日志语句!


0
投票
当您使用 array.reduce 时,为什么不使用 array.map 为数组添加初始值(而不是使用 for 循环)?

function seedArray(start, end) { return Array.apply(null, new Array(end - start + 1)).map( function(x, i) { return i + start; } ); }

当然你可以做一些错误检查以确保 p1 和 p2 是非负整数并且 p2 >= p1 以确保 new Array() 不会崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.