
本文提供一种基于已知质数数组动态筛除的算法,用于准确计算第n个质数,重点修复了循环计数逻辑错误与数组索引越界问题,并给出可运行的java实现。
本文提供一种基于已知质数数组动态筛除的算法,用于准确计算第n个质数,重点修复了循环计数逻辑错误与数组索引越界问题,并给出可运行的java实现。
在不使用标准库 isPrime() 函数的前提下,生成第 n 个质数的核心思路是:维护一个已发现质数的数组,用其中每个质数试除候选数,若均不能整除,则该候选数为新质数。然而,原始代码存在两个关键逻辑缺陷,导致输入大于 2 时程序陷入死循环或写入错误位置,最终无输出。
首要问题是变量 num_primes 的作用域和更新时机错误:它被错误地定义在 do-while 循环体内,每次迭代都重置为 0,导致 primes[num_primes] = prime 实际始终写入 primes[1],覆盖第二个质数(即 3),而 primes[2] 及后续位置永远保持初始值 0,使循环条件 primes[num - 1] == 0 永远为真,程序卡死。
其次,num_primes++ 被无条件执行,而非仅在确认找到新质数后递增,这进一步加剧了索引错位和数组填充失效。
以下是修复后的完整可运行代码:
import java.util.Scanner;
class PrimeNumberFinder {
static boolean is_prime(int number, int[] prime_numbers) {
for (int prime : prime_numbers) {
if (prime == 0) break; // 遇到未初始化项,终止检查
if (number % prime == 0) {
return false;
}
}
return true;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the nth prime number you want: ");
int n = scanner.nextInt();
if (n <= 0) {
System.out.println("n must be a positive integer.");
return;
}
int[] primes = new int[n];
primes[0] = 2; // 第一个质数是2
int candidate = 2; // 当前待检测数(从2开始递增)
int count = 0; // 已找到质数个数,初始为1(因primes[0]已设为2)
// 当尚未填满primes数组时继续搜索
while (count < n - 1) {
candidate++;
if (PrimeNumberFinder.is_prime(candidate, primes)) {
primes[++count] = candidate; // 找到新质数,先递增再赋值
}
}
System.out.printf("The %d%s prime number is %d%n",
n,
n == 1 ? "st" : n == 2 ? "nd" : n == 3 ? "rd" : "th",
primes[n - 1]);
scanner.close();
}
}关键改进说明:
- ✅ count 变量声明在循环外,准确跟踪已存质数数量(初始 count = 0 对应 primes[0] = 2);
- ✅ 使用 while (count < n - 1) 替代易出错的 do-while + 零值判断,逻辑更清晰、终止条件明确;
- ✅ is_prime() 中添加 if (prime == 0) break,避免遍历未初始化数组元素,提升健壮性;
- ✅ 输出格式增强可读性,自动添加序数后缀(1st, 2nd, 3rd...);
- ✅ 补充输入校验,防止非法输入导致异常。
注意事项:
- 该算法时间复杂度约为 O(n² log n),适用于 n ≤ 10⁴ 场景;如需更高性能,建议升级为埃氏筛或分段筛;
- 数组 primes 长度固定为 n,内存占用可控,但不可动态扩容;
- candidate 从 2 开始递增,虽包含偶数,但因 is_prime(4, [...]) 等会快速返回 false,实际开销可接受。
通过修正变量生命周期与条件触发逻辑,本方案实现了简洁、正确、可扩展的第 n 个质数生成器,是理解质数判定与增量构造思想的优秀实践范例。

















