You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS与Haskell埃拉托斯特尼筛法对比及获取前N个质数方案咨询

实现返回前n个质数的函数

你原有实现的限制在于预先固定了输入数字序列的上限为n,因此只能返回小于等于n的质数。要实现和Haskell版本类似的灵活调用,我们可以用JavaScript的**Generator(生成器)**模拟懒求值的无限序列,完全对齐Haskell的实现逻辑:

// 无限质数生成器,对应Haskell的 primes 定义
function* primesGenerator() {
  // 从2开始的无限整数序列,对应Haskell的 [2..]
  function* infiniteInts() {
    let num = 2;
    while (true) yield num++;
  }

  // 筛法逻辑,和Haskell版完全对应
  function* sieve(numbers) {
    const first = numbers.next().value;
    yield first;
    // 过滤掉能被first整除的数,递归筛剩下的序列
    yield* sieve((function* filtered() {
      for (const n of numbers) {
        if (n % first !== 0) yield n;
      }
    })());
  }

  yield* sieve(infiniteInts());
}

// 取前n个质数,对应Haskell的 take n primes
function takePrimes(n) {
  const result = [];
  const primeGen = primesGenerator();
  for (let i = 0; i < n; i++) {
    result.push(primeGen.next().value);
  }
  return result;
}

// 取满足条件的质数,对应Haskell的 takeWhile cond primes
function takePrimesWhile(condition) {
  const result = [];
  const primeGen = primesGenerator();
  while (true) {
    const nextPrime = primeGen.next().value;
    if (!condition(nextPrime)) break;
    result.push(nextPrime);
  }
  return result;
}

调用示例:

  • 取前1000个质数:takePrimes(1000)
  • 取小于1000的所有质数:takePrimesWhile(x => x < 1000)

解决栈溢出问题

你原有递归实现的栈溢出是因为递归深度等于质数的个数,当质数数量超过JS引擎的最大调用栈限制时就会报错。
首先要注意:目前只有Safari浏览器实现了ES6标准的尾调用优化,Chrome、Node.js等运行环境都不支持,所以靠尾递归优化无法解决通用场景的栈溢出问题,最稳妥的方案是把递归逻辑改为迭代实现:

// 迭代版无限质数生成器,无栈溢出问题
function* iterablePrimes() {
  const foundPrimes = [];
  let current = 2;
  while (true) {
    // 逻辑等价于递归筛法:只用已找到的质数校验,效率更高
    const isPrime = foundPrimes.every(p => current % p !== 0);
    if (isPrime) {
      foundPrimes.push(current);
      yield current;
    }
    current++;
  }
}

这个迭代版本的逻辑和埃氏筛完全一致,不会产生调用栈累积,即使取前十万个质数也不会出现栈溢出,性能也比递归版本更优。


内容的提问来源于stack exchange,提问作者Pastilhas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 04:06:03