素数发生器逻辑

Sha*_*nia 2 java primes

我应该创建一个类PrimeNumberGenerator,它有一个方法nextPrime可以打印出所有素数,直到用户输入的数字.

例)

Enter a Number: 
20
2
3
5
7
11
13
17
19
Run Code Online (Sandbox Code Playgroud)

我们的老师告诉我们,我们应该使用嵌套for循环.我试过了,但是当我试图制作内部(嵌套)循环时,我真的很困惑.

这是我的代码:(我稍后会做一个测试课)

public class PrimeGenerator {

    private int num;
    boolean isPrime;

    public PrimeGenerator(int n)
    {
        num = n;
    }

    public int nextPrime (int num)
    {
        for (int i=2; i < num; i++) // The first prime number is 2 and the prime numbers only have to go up to a number the user inputs. 
        {
            for (int j = 3; j<=i/2; j+=2) // The next prime number is 3 and I attempted to loop through to get the next odd number.
            {
                if (num % i == 0) //if the number (upper limit) mod a "prime number" is 0, then that means that number is not really "prime" after all. 
                {
                    break;
                }
            }
        }

        return num;
    }

}
Run Code Online (Sandbox Code Playgroud)

Haa*_*eit 7

这里有两个你忘了问的问题:

  • 为什么嵌套循环会使一切变得如此复杂?
  • 我该怎样做才能让事情再次复杂化?

让我们一起玩你实际问的问题,然后回答前两个问题.

您想要做的事情可以这样描述:对于每个数字,1-n,其中n由用户输入,如果它是素数则打印它.

好的,让我们在这里写下伪代码/逻辑.它看起来像Java,但事实并非如此.这只是为了传达我们的目标:

int largestNumber = readIntegerFromKeyboard();

for all ints i from 1 to largestNumber {
    if(isPrime(i)) {
        println(i);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,让我们这样做!但首先,我们需要一份清单,列出我们需要做的所有事情:

  • 从键盘读取整数
  • 循环数字
  • 检查数字是否为素数
  • 打印素数(带换行符)

让我们先做两件容易的事.读取输入并设置循环:

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();
Run Code Online (Sandbox Code Playgroud)

好的,这似乎很简单.到目前为止,这里的一切都有意义.这很容易理解逻辑.然而,现在,当我们用实际逻辑替换isPrime时,一切都将变得混乱且难以阅读.

因此,让我们尽可能简单地理解这段代码.我们将不使用任何技巧来加速代码.可读性和正确性是我们唯一关心的两件事.我们将使用模运算符来检查某些东西是否可以均匀分割.Modulo就像整数除法,除了它返回余数而不是结果.所以7/2 = 2. 7%2 = 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);
    }
}    
Run Code Online (Sandbox Code Playgroud)

所以好消息是,这是有效的.坏消息是,这比必要的阅读更难.我们在这里做的不是很多.当我写这篇文章时,我犯了几个愚蠢的错误,混淆了变量.也许我很蠢.所以也许我应该在那种情况下写出愚蠢的代码.;)另一方面,你不是傻瓜.但是你可能和我一起工作,这愚蠢的,所以你必须自己编写愚蠢的代码,这样你才能有效地与我合作.

最大的问题是我们在另一个循环的中间有这个大规模的循环.这就是让我失望的原因.我提到了错误的循环变量.但为什么我们需要循环中的循环?读起来不是很舒服:

if(isPrime(i)) {
    System.out.println(i);
}
Run Code Online (Sandbox Code Playgroud)

而不是整个混乱?你的教授指出了嵌套循环.但是它让你失望了.相反,只需编写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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这对我来说更容易阅读.不是因为逻辑变得更容易了,但由于只有 一点我不得不关心要么是:

  • 检查所有数字并打印正确的数字,或
  • 如何检查数字是否为素数.

由于这两个独立的东西现在是分开的,你可以立刻想一想.高兴,因为你刚刚做了一个适当的抽象.这使您的代码更容易理解,因为它将这两个问题分开.这是制作大型项目的关键方式.你采取困难的事情并自己做.然后你可以自己测试它们,并自己使用它们.

(现在我只需要等待回答你没有明确要求的问题的downvotes ......)