如何召回一个功能,Eratosthenes筛选

时间:2015-01-19 19:44:37

标签: java sieve-of-eratosthenes

我正在尝试编写能够使用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;
}

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

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

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

第28行是我回忆起函数:int secondNumber[] = markOfMultiples(n, numbers, currentNumber);

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

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

P.S。请原谅变量名称,因为我将在程序运行时更改它们。

2 个答案:

答案 0 :(得分:3)

如果你想让这种方法有效,你可以做@Thierry建议的修复,先在你的while循环中检查count2 < n然后再包围这行

numbers[count2] = 0
使用if子句检查count2的

不会超出索引的末尾。 e.g。

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

您最后的挑战是当n变得更大时,如何足够多次调用markOfMultiples()函数。这不是你的基本方法的问题 - 你绝对可以做到这一点,你的方法将运作良好,并且对于低数字(例如高达10000)具有可接受的性能。

然而

我意识到这是一项任务,你想按照自己的方式去做,但是你可能想要考虑一些你的方法的功能 - 也许在你完成它之后。

  1. 可读性 - 对于查看(标记)代码的人来说,理解它正在做什么并验证它是否能为所有n值做正确的事情会很容易吗?
  2. 尽量不要重复自己 - 例如考虑填充numbers数组的位置:

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

    xnewNumberoriginalNumber不同吗?你需要两个变量吗?这种排序或重复发生在代码的其他地方 - 坚持的原则称为DRY (Don't Repeat Yourself)

  3. 是否有更简单的方法可以在markOfMultiples()方法的true位置移动索引? (提示:是的,有)

  4. 你真的需要数字[]数组中的实际数字吗?如果你弄清楚如何重复调用你的markOfMultiples以获得高n值,那么你最终会得到很多零并且素数会作为整数值。如果使用数组索引给出素数,那么1和0(或false s和{{1}} s)的数组是否足够?

答案 1 :(得分:1)

你需要测试count2&lt; n在访问号码之前[count2]:

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