Sieve of Erathostenes ArrayIndexOutOfBounds

2019-08-03 21:55发布

trying to implement a simple sieve of erathosthenes to solve this question on project euler :

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.

Link

My code keeps returning this error however :

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2147479015 at Prime.main(Prime.java:28)

Can anyone give me any hints as to why? Here is the code:

import java.math.BigInteger;

public class Prime {
    /*
     * Input: an integer n > 1
     * 
     * Let A be an array of bool values, indexed by integers 2 to n, initially
     * all set to true.
     * 
     * for i = 2, 3, 4, ..., while i^2 ≤ n: if A[i] is true: for j = i^2, i^2 +
     * i, i^2 + 2i, ..., while j ≤ n: A[j] = false
     * 
     * Now all i such that A[i] is true are prime.
     */

        import java.math.BigInteger;

public class Prime {
    /*
     * Input: an integer n > 1
     * 
     * Let A be an array of bool values, indexed by integers 2 to n, initially
     * all set to true.
     * 
     * for i = 2, 3, 4, ..., while i^2 ≤ n: if A[i] is true: for j = i^2, i^2 +
     * i, i^2 + 2i, ..., while j ≤ n: A[j] = false
     * 
     * Now all i such that A[i] is true are prime.
     */

    public static void main(String[] args) {
        boolean[] array = new boolean[2000000];
        BigInteger counter = new BigInteger("0");
        for (int value = 0; value < array.length; value++) {
            array[value] = true;
        }
        for (int i = 2; i < array.length; i++) {
            if (array[i]) {
                int j = i * i;
                while (j > 0 && j < array.length) {
                    array[j] = false;
                    j += i;
                }
            }
        }
        for (int i = 2; i < array.length; i++) {
            if (array[i]) {
                counter = counter.add(BigInteger.valueOf(i));
            }
        }
        for (int value = 2; value < array.length; value++) {
            if(array[value]){
                System.out.println(value + ", ");
            }
        }
        System.out.println("\n" + counter);

    }

}

2条回答
闹够了就滚
2楼-- · 2019-08-03 22:33

Not to be snarky, but it's because you're going out of the bounds of the array. Your limit for i is the length of the array, and then j is equalling at a minimum the square of i. j is then being used as the location of the array to be accessed at line 28, which is out of bounds.

查看更多
干净又极端
3楼-- · 2019-08-03 22:43

The problem is coming from these lines:

        int j = i * i;
        while (j <= array.length) {
            array[j] = false;
            j += i;
        }

What's happening is that sometimes i * i is so big that it rounds the corner (overflows) and becomes negative. Java does not have 'checked' integer math. To fix this, you'll want to change your while condition to the following

while(j > 0 && j < array.length)

Also, your array is of size 200,000 and not 2,000,000.

查看更多
登录 后发表回答