我正在尝试编写使用Eratosthenes筛子算出质数的代码。我必须包含一个函数,该函数将接受一个数字并乘以该数字的所有倍数。为了进行测试,我将第一个数字设置为2,将第二个数字设置为3。它适用于第一个数字,但不适用于第二个数字(无论数字的顺序如何,即我是否首先将3放入函数中)。我知道那里还有其他的Eratosthenes筛网,但我想尝试用我最初想到的方式来做。

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Scanner input = new Scanner(System.in);
    System.out.println("Which number would you like to calculate up to?");
    int n = input.nextInt();
    input.close();

    int x = 0;
    int newNumber = 2;
    int numbers[] = new int[n];
    while(newNumber <= n){
        numbers[x] = newNumber;
        x++;
        newNumber++;
    }

    int currentNumber = 2;
    int finalNumber[] = markOfMultiples(n, numbers, currentNumber);
    for(int y = 0;y < n-1;y++){
        System.out.print(finalNumber[y] + ", ");
    }

    currentNumber = 3;
    int secondNumber[] = markOfMultiples(n, numbers, currentNumber);
    for(int y = 0;y < n-1;y++){
        System.out.println(secondNumber[y]);
    }

}

public static int[] markOfMultiples(int n, int numbers[], int currentNumber){

    int originalNumber = currentNumber;
    while(currentNumber<n){
        currentNumber = currentNumber + originalNumber;
        int count2 = 0;
        while(currentNumber != numbers[count2] && currentNumber<=n && count2<n){
            count2++;
        }
        numbers[count2] = 0;
    }
    return numbers;
}


我得到的错误是:线程“主”中的异常java.lang.ArrayIndexOutOfBoundsException:20

在sieveOfEratosthenes.sieveOfEratosthenes.markOfMultiples(sieveOfEratosthenes.java:46)

在sieveOfEratosthenes.sieveOfEratosthenes.main(sieveOfEratosthenes.java:28)

第28行是我想起函数的时间:int secondNumber[] = markOfMultiples(n, numbers, currentNumber);

第46行是while(currentNumber != numbers[count2] && currentNumber<=n && count2<20){

任何帮助将非常感激。如何继续调用该函数?

ps。请原谅变量名,因为在程序运行时我将对其进行更改。

最佳答案

如果您想使这种方法起作用,可以执行@Thierry建议的修复,以在while循环中先检查count2 < n,然后再将其包围

numbers[count2] = 0


使用if子句检查count2是否不超出索引的末尾。例如

if (count2 < n) {
    numbers[count2] = 0;
}


最后的挑战是当n变大时,如何多次调用markOfMultiples()函数。这不是您的基本方法的问题-您可以做到这一点,并且您的方法可以很好地工作,并且对于低位数字(例如10000个)具有可接受的性能。

然而

我意识到这是一项任务,您想按自己的方式去做,但是您可能需要考虑该方法的一些功能-也许在使它起作用之后。


可读性-看着(标记)您的代码的人很容易理解它在做什么,并验证它是否对所有n值都能正确地工作?
尽量不要重复自己-例如考虑填充numbers数组的位置:

while(newNumber <= n){
   numbers[x] = newNumber;
   x++;
   newNumber++;
}


xnewNumber会有所不同吗?您是否需要两个变量?这种排序或重复发生在代码的其他位置-遵循的原理称为DRY (Don't Repeat Yourself)
有没有更简单的方法可以将索引移至originalNumber方法中的markOfMultiples()位置? (提示:是的,有)
您是否真的需要numbers []数组中的实际数字?如果您想出如何为n的高值重复调用markOfMultiples,那么最终将得到很多零,并且质数会保留为整数值。如果使用数组索引为您提供质数,那么一个1和0(或true s和false s)数组是否足够?

10-07 12:59