微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用埃拉托色尼筛法的最大素数

如何解决使用埃拉托色尼筛法的最大素数

我设法解决了问题,但超出了时间限制。

解决的问题:如果给定的数字 n 非常大,则需要花费大量的时间。

问题有没有办法调整代码以更快地获得最后一个质数?

const n = 126;
let lastPrime = 0;

for (let j = 2; j <= n; j++) {
    let counter = 0;
    for (let i = 1; i <= j; i++) {
        if (j % i === 0) counter++;
    }
    if (counter === 2) lastPrime = j;
}

print(lastPrime); // Biggest prime number of 126 is 113

谢谢!

解决方法

这里有很多优化要做 - 在这里快速阅读 (https://math.stackexchange.com/questions/889712/the-fastest-way-to-count-prime-number-that-smaller-or-equal-n/893767) 会有所帮助。

但对于初学者来说,您可以更改代码中的一些内容以使其更快:

第 1 步:减少外部迭代次数,因为我们知道所有偶数都是非质数。

for (let j = 3; j <= n; j += 2) {
...
}

第 2 步:通过仅迭代最大数量的 Sqrt 来减少内循环。一旦我们找到一个因素,也要跳出内部循环。不需要迭代到最后。这两个将为您带来最大的胜利。

let prime = true;    
for (let i = 2; i <= Math.sqrt(j); i++) { 
  if (j % i === 0) {
    prime = false;
    break;
  }
}
if (prime) {
  lastPrime = j;
}

第 3 步:停止计算 Math.sqrt(j),因为您已经知道先前的最大值。 sqrt 是一个(相对)昂贵的操作。我们可以通过使用以前的值来避免它。

let maxBound = 2;
let maxSquare = maxBound * maxBound;

for (let j = 3; j <= n; j += 2) {
  if (maxSquare < j) {
    maxBound++;
    maxSquare = maxBound * maxBound;
  }
  for (let i = 2; i <= maxBound; i++) {
  ...
  }
}

第 4 步:如果您只想要最大的质数,请向后循环并在找到一个质数后立即中断。

这是完成的程序,它应该比你的程序快大约 2 个数量级。请注意,虽然我为您的程序提供了一些微不足道的优化,但与您可以在此处找到的算法优化相比,这总是显得苍白无力:https://math.stackexchange.com/a/893767

function getMaxPrime(n) {
  for (let j = n; j >= 3; j --) {
    let prime = true;
    for (let i = 2; i <= Math.sqrt(j); i++) {
      if (j % i === 0) {
        prime = false;
        break;
      }
    }
    if (prime) {
      maxPrime = j;
      break;
    }
  }

  console.log(maxPrime);
}
,

我在查看筛选代码时问自己的一个基本问题是:“此代码是否使用模 (%) 运算符?”如果是这样,那就不是埃拉托色尼筛。你正在做试验部门,这要慢得多。现在试分肯定是有地方和原因的,但是根据你的问题标题,你打算使用SoE。

例如参见 Wikipedia pseudocode。唯一的操作是仅涉及简单加法、测试和集合的两个循环。而已。没有乘法,没有除法,没有模数。这绝对是算法运行速度快的关键。内循环也很快变得稀疏,因为增量不断变大,所以我们实际上运行内循环代码的次数越来越少。与您发布的初始代码形成对比,其中内循环运行 更多 次。

要进行基本的 SoE,您需要一个小数组,然后只需要 4 行代码来进行筛选,外层循环执行 sqrt(n)。然后你可以检查只剩下素数标记的数组。在您的情况下,您可以向后走并在找到第一次出现时返回。有无数的优化方法,但令人惊讶的是,对于相对较小的 n(例如,在 10^9 以下,您确实需要进行分段 SoE),简单的基本 SoE 的速度有多快。

综上所述,您获得了可工作的代码,这是一个很好的第一步。一旦某事起作用,尝试不同的方法会容易得多。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。