埃拉托斯特尼筛法循环中调用isPrime始终返回false求助
问题分析与解决方案
核心问题
你的代码问题出在factorList.js的全局变量factors上:这个数组是全局声明的,每次调用factorList时只会追加因数到数组中,不会清空。第一次调用isPrime(7)时,factors是[1,7],长度为2返回true;但第二次调用时,数组已经累积了之前的所有元素,长度远大于2,所以返回false。这就是循环内调用isPrime全部返回false的根本原因。
另外原代码还有两个隐性问题:
factorList中循环从i=0开始,num%0会触发Division by zero错误- 主程序最后一行
console.log(primes.join(,);缺少闭合括号,属于语法错误
修正代码
方案1:修复全局数组问题(最小改动)
修改factorList.js,每次调用前清空全局数组,并修正循环起始值:
const factors = []; const factorList = (num) => { factors.length = 0; // 每次调用前清空数组 for (let i = 1; i <= num; i++) { // 从1开始,避免除零错误 if (num % i === 0) { factors.push(i); } } };
方案2:使用局部数组(更优,避免全局污染)
重构factorList.js,用局部数组返回结果,彻底消除全局变量问题:
const factorList = (num) => { const factors = []; // 局部数组,每次调用重新创建 for (let i = 1; i <= num; i++) { if (num % i === 0) { factors.push(i); } } return factors; // 返回因数数组 };
同时修改numPropFuncs.js,接收返回的数组:
const factorList = require(`./factorList.js`); const isPrime = num => { const factors = factorList(num); return factors.length === 2; // 简化判断逻辑 };
修正主程序语法错误
把最后一行的console.log(primes.join(, );改为:
console.log(primes.join(', '));
额外优化:实现真正的埃拉托斯特尼筛法
你的原代码本质是逐个判断质数,并没有实现埃拉托斯特尼筛法的核心逻辑(标记非质数)。如果要实现标准筛法,可参考以下高效代码:
const limit = 30; const eratosthenesSieve = num => { const sieve = new Array(num + 1).fill(true); sieve[0] = sieve[1] = false; // 0和1不是质数 // 遍历到根号num即可,之后的非质数已被标记 for (let i = 2; i <= Math.sqrt(num); i++) { if (sieve[i]) { // 标记当前质数的所有倍数为非质数 for (let j = i * i; j <= num; j += i) { sieve[j] = false; } } } // 筛选出所有标记为true的索引(即质数) return sieve.map((isPrime, index) => isPrime ? index : null).filter(Boolean); }; const primes = eratosthenesSieve(limit); console.log(primes.join(', '));
内容的提问来源于stack exchange,提问作者ScorchedField
相关产品推荐
相关产品推荐

