代码之家  ›  专栏  ›  技术社区  ›  ScorchedField

JavaScript|导入的模块在循环内部中断

  •  1
  • ScorchedField  · 技术社区  · 2 年前

    我正在编写一个程序,它可以将埃拉托斯梯尼的筛选达到给定的极限。这是当前代码:

    const { isPrime } = require(`./numPropFuncs.js`);
    
    const limit = 30;
    const primes = [];
    
    const eratosthenesSieve = num => {
        for (let i = 0; i <= num; i++) {
            if (isPrime(i)) {
                primes.push(i);
            };
        };
    };
    
    eratosthenesSieve(limit);
    
    console.log(primes.join(`, `);
    

    它导入以下模块来测试一个数字是否为素数:

    const resources = require(`./factorList.js`);
    
    const isPrime = num => {
        resources.factorList(num);
        if (resources.factors.length === 2) {
            return true;
        } else {
            return false;
        };
    };
    

    依次导入以下模块,该模块提供给定数量的所有因子的数组:

    const factors = [];
    
    const factorList = (num) => {
      for (let i = 0; i <= num; i++) {
        if (num % i === 0) {
          factors.push(i);
        };
      };
    };
    

    这两个模块都经过了测试,以确保它们正常工作,并已正确导入。 问题是当 isPrime() 在的for循环内部调用 eratosthenesSieve() 它返回 false 对于每次迭代,包括当素数作为参数传递时。

    我正在测试 eratosthenesSieve() 使用30作为极限,因为很容易验证结果。记录的输出应该是字符串: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 。相反,它要么不记录任何内容,要么在记录的情况下 primes 没有 .join() , [].在拥有循环日志之后 ${i}: ${isPrime(i)} 在我实现的每一次迭代中 isPrime() 正在返回 false 对于每个数字(即记录“0:false”…“30:false”)。我测试过 isPrime() 的外部 eratosthenesSieve() 和里面 eratosthenesSieve() 但在for循环之外,两次都正常工作。

    我想这可能是范围问题,所以我尝试使用一个单独的变量,在内部声明 eratosthenesSieve() 但在循环之外,作为测试编号而不是i:

    const eratosthenesSieve = num => {
        let testNumber = 0;
        for (let i = 0; i <= num; i++) {
            if (isPrime(testNumber)) {
                primes.push(testNumber);
            };
            testNumber++;
        };
    };
    

    这解决了我在另一个程序的循环中遇到的另一个问题,尽管该程序没有使用 isPrime() ,(我不记得那个节目的问题是什么了)。然而,该解决方案不适用于Eratosthenes的筛分程序。

    我试着简单地登录 ${7}: ${isPrime(7)} 在每次迭代中,同时注释掉内部的其余代码 eratosthenesSive() 只是想看看会发生什么。奇怪的是,它记录了 7: true 在第一次迭代中(显然是正确的输出),但记录 7: false 在29次连续迭代中的每一次上。

    最后,我尝试重构以使循环从1开始,以防从0开始导致问题。这也于事无补。

    我不知道这里发生了什么以及如何解决。非常感谢您的帮助。(我的运行时环境是MacOS Sonoma上VS代码中的Node.js)

    1 回复  |  直到 2 年前
        1
  •  0
  •   Nick Parsons Felix Kling    2 年前

    您正在修改 factors 的每个调用的数组 isPrime() 功能而无需重置。因为 因素 是全球性的,即使在 isPrime() / factorsList() 函数已完成执行。例如,如果您拨打 isPrime(1) 然后 resources.factors 更新为:

    [1]
    

    然后在下一次迭代中,您调用 isPrime(2) ,导致推 1 2 在之前的结果上,现在 资源.因素 将:

    [1, 1, 2]
    

    从这里开始, 资源.因素 不断成长,意味着你 resources.factors.length === 2 登记入住 isPrime() 永远不会 true .

    相反,制作 因素 本地到 factorsList 函数,以便每次调用 因素列表 是独立的,并返回 因素 只是为了那个电话:

    const factorList = (num) => {
      const factors = [];
      for (let i = 0; i <= num; i++) {
        if (num % i === 0) {
          factors.push(i);
        }
      }
      return factors;
    };
    
    module.exports.factorList = factorList;
    

    然后您可以在 isPrime 功能:

    const isPrime = (num) => {
      const factors = resources.factorList(num);
      return factors.length === 2;
    };