这里有两个问题你忘记问了:
- 为什么嵌套循环让一切变得如此复杂?
- 我能做些什么来让事情再次变得简单?
因此,让我们先回答您实际提出的问题,然后回答前两个问题。
您想要做的事情可能可以这样描述:
对于每个数字 1-n(其中 n 由用户输入),如果它是素数,则打印它。
好的,让我们在这里编写伪代码/逻辑。
它看起来像 Java,但事实并非如此。它只是为了传达我们的目的:
int largestNumber = readIntegerFromKeyboard();
for all ints i from 1 to largestNumber {
if(isPrime(i)) {
println(i);
}
}
那么让我们这样做吧!但首先,我们需要一份包含所有需要做的事情的清单:
- 从键盘读取整数
- 循环数字
- 检查该数字是否是质数
- 打印素数(带换行符)
让我们先做两件简单的事情。读取输入并设置循环:
Scanner keyboard = new Scanner(System.in);
int largestNumber = keyboard.nextInt();
for(int i = 1; i <= largestNumber; ++i) {
if(isPrime(i)) {
System.out.println(i);
}
}
keyboard.close();
好吧,这看起来很简单。到目前为止,这里的一切都是有道理的。逻辑很容易理解。
然而现在,当我们用实际逻辑替换 isPrime 时,一切都会变得混乱且难以阅读。
因此,让我们将这段代码写得尽可能容易理解。我们不会使用任何技巧来加速代码。可读性和正确性是only我们会关心两件事。我们将使用模运算符来检查某物是否可整除。取模类似于整数除法,只不过它返回余数而不是结果。所以 7 / 2 = 2。7 % 2 = 1,因为还剩下 1 个。
Scanner keyboard = new Scanner(System.in);
int largestNumber = keyboard.nextInt();
for(int i = 1; i <= largestNumber; ++i) {
// checks if the number is a prime or not
boolean isPrime = true;
for(int check = 2; check < i; ++check) {
if(i % check == 0) {
isPrime = false;
}
}
if(isPrime) {
System.out.println(i);
}
}
好消息是,这有效。
坏消息是,这比必要的更难阅读。我们在这里能做的并不多。当我写这篇文章时,我犯了几个愚蠢的错误,混淆了变量。也许我很傻。所以也许在这种情况下我应该编写防愚蠢的代码。 ;) 另一方面,你并不愚蠢。但你可以和我一起工作is愚蠢,所以你必须自己编写愚蠢的代码,这样你才能高效地与我合作。
最大的问题是我们在另一个循环的中间有这个巨大的循环。这就是让我绊倒的原因。我引用了错误的循环变量。但为什么我们需要循环中的循环呢?读起来是不是舒服多了:
if(isPrime(i)) {
System.out.println(i);
}
而不是那一团糟?你的教授指出了嵌套循环。但它让你失望了。相反,只需编写 isPrime 方法即可。事实是,对于我遇到过的每个嵌套循环实例来说都是如此。所以让我们看看它会是什么样子:
class Homework {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int largestNumber = keyboard.nextInt();
for(int i = 1; i <= largestNumber; ++i) {
if(isPrime(i)) {
System.out.println(i);
}
}
keyboard.close();
}
/**
* Checks is a positive integer is a prime number
*/
public static boolean isPrime(int number) {
for(int check = 2; check < number; ++check) {
if(number % check == 0) {
return false;
}
}
return true;
}
}
对我来说,这更容易阅读。不是因为逻辑变得更容易,而是因为only thing我必须关心的是:
- 检查所有数字并打印正确的数字,或者
- 如何检查一个数是否是质数。
由于这两个独立的事情现在分开了,所以你需要同时考虑的事情就少了很多。庆幸吧,因为你刚刚完成了正确的抽象。这使您的代码更容易理解,因为它分离了两个问题。这是制作大型项目的关键方法。你把困难的事情自己解决。然后你可以自己测试它们,并自己使用它们。
(现在我只需要等待反对票来回答你没有明确提出的问题......)