必须完整统计所有素因子(含重数)个数且总数严格等于2;常见错误是仅找一个因子后判断商是否为素数,这在n有≥3个素因子或含重因子(如8=2³)时会误判,正确做法是试除并累计素因子个数,超2即终止。

直接结论:不能只找一个因子再判断商是不是素数,必须完整统计所有素因子(含重数)个数,且总数严格等于 2。
为什么 is_prime(n / d) 会误判
常见写法是遍历 i 从 2 到 sqrt(n),一找到能整除的 i 就立刻检查 is_prime(i) 和 is_prime(n / i)。这在 n = p × q(两个大素数)时看似可行,但一旦 n 有 ≥3 个素因子就会崩:
-
n = 12:i = 2整除 →n / i = 6,is_prime(6)返回false,于是返回false(正确) -
n = 30:i = 2整除 →n / i = 15,is_prime(15)返回false,也返回false(碰巧对) -
n = 60 = 2×2×3×5:i = 2整除 →n / i = 30,is_prime(30)是false,返回false;但若你换顺序或用别的因子,逻辑就不可靠——它依赖“第一次找到的因子是否恰好把剩余部分压成素数”,这不是判定依据
更隐蔽的问题是:你没验证 i 是否真的只出现一次。比如 n = 4,i = 2 整除,n / i = 2 是素数,没问题;但 n = 8,i = 2 整除,n / i = 4 不是素数,返回 false —— 正确。可一旦你没处理 i 的重复出现(即没做 while 除尽),就可能漏掉重数。
必须用试除 + 计数,且提前剪枝
核心是模拟质因数分解过程,边除边计数,一旦超过 2 就终止:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 特判
n → 直接返回 <code>false(最小半素数是 4) - 用
int cnt = 0累加素因子重数 for (int i = 2; i * i :注意用 <code>i * i ,不是 <code>i ,避免浮点误差和类型转换- 每次
if (n % i == 0)成立时,进while (n % i == 0)循环,每除一次cnt++,并立即检查if (cnt > 2) return false - 循环结束,若
n > 1,说明剩下一个素因子,cnt++ - 最终返回
cnt == 2
这个流程天然保证:每个 i 都是素数(因为更小的因子已被除尽),无需额外调用 is_prime(),也避免了重复素性判断开销。
i * i 溢出与边界细节
当 n 接近 INT_MAX(约 2.1e9)时,i * i 在 int i 下可能溢出,导致循环条件失效。实际中:
- 若
n ≤ 1e9,i最大到 ~31622,int安全 - 若
n可达1e10或更高,应将i声明为long long,或改用i (整除比较,无溢出风险) -
n == 1必须特判,否则循环不进,n > 1条件会误加一次计数 -
n == 2或n == 3是素数,不是半素数,n 特判已覆盖
真正容易被忽略的,不是算法主干,而是 while 内部没做 cnt > 2 的即时退出 —— 这会让 n = 2×2×2×1000000007 这类数继续执行无意义的试除,既慢又可能多计。

















