本文详解 JavaScript 质数判断逻辑常见错误:原代码因在内层循环中错误地递增 i 并无条件添加元素,导致 33、35 等合数被误判为质数;修正方案是引入布尔标志位,仅在确认无因子后才收录质数。
本文详解 javascript 质数判断逻辑常见错误:原代码因在内层循环中错误地递增 `i` 并无条件添加元素,导致 33、35 等合数被误判为质数;修正方案是引入布尔标志位,仅在确认无因子后才收录质数。
原始代码的核心问题在于控制流与逻辑判断的严重错位。具体表现为:
- 内层 for (let j = 2; j
- 此时 i 已被修改(例如 i 原为 33,检测到 33 % 3 === 0 后变为 34),随后无条件将新值 i(即 34)写入 prime 数组;
- 更严重的是,该逻辑使所有合数都会“跳过”自身、强行录入下一个数,最终导致 33 和 35 这类明显可分解的数(33 = 3×11,35 = 5×7)被错误包含。
✅ 正确做法是:分离“检测”与“收集”逻辑——用布尔标志 primeFlag 记录是否找到因子,内层循环仅负责判断,外层再根据标志决定是否推入结果。
以下是优化后的完整实现(含关键注释和边界优化):
function primeFinder(n) {
if (n < 2) return []; // 小于2无质数,提前返回空数组
const prime = [];
for (let i = 2; i <= n; i++) {
// 只需检查到 sqrt(i),且 Math.sqrt(i) 向上取整更安全(如 i=4, sqrt=2;i=9, sqrt=3)
const root = Math.ceil(Math.sqrt(i));
let isPrime = true;
for (let j = 2; j <= root; j++) {
if (i % j === 0) {
isPrime = false;
break; // 找到因子即终止,提升效率
}
}
if (isPrime) {
prime.push(i); // 仅当确认为质数时才添加
}
}
return prime;
}
console.log(primeFinder(35));
// 输出: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]? 关键改进点总结:
立即学习“Java免费学习笔记(深入)”;
- ✅ 移除危险的 i++ 操作:它破坏了外层循环的自然递进,是根本性 bug;
- ✅ 使用 isPrime 标志替代隐式控制流,语义清晰、易于维护;
- ✅ 采用 Math.ceil(Math.sqrt(i)) 替代 Math.floor(如 i=25 时 sqrt=5,floor 无影响,但 ceil 更鲁棒);
- ✅ 使用 push() 替代手动索引赋值(prime[index] = i; index++),避免潜在越界或稀疏数组问题;
- ✅ 添加 n
? 进阶提示:对于更大范围(如 n > 10⁵),建议改用「埃拉托斯特尼筛法」(Sieve of Eratosthenes),时间复杂度从 O(n√n) 降至 O(n log log n),大幅提升性能。但对教学与中小规模场景,上述标志位方案逻辑直观、易于理解与调试。


















