【问题标题】:Sieve of Erathostenes ArrayIndexOutOfBounds埃拉托色尼筛法 ArrayIndexOutOfBounds
【发布时间】:2011-10-09 23:47:22
【问题描述】:

尝试在项目 euler 上实现一个简单的 Erathostenes 筛来解决这个问题:

10 以下的素数之和为 2 + 3 + 5 + 7 = 17。

求两百万以下的所有素数之和。

Link

然而,我的代码一直返回此错误:

线程“主”java.lang.ArrayIndexOutOfBoundsException 中的异常: -2147479015 在 Prime.main(Prime.java:28)

谁能告诉我为什么?代码如下:

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);

    }

}

【问题讨论】:

  • 温馨提示,如果您发现答案有帮助,您应该将其标记为已接受。你的其他问题也一样。
  • 这不是你错误的原因,而是为了效率i只需要计算i * i &lt; array.length的位置。要调试您的代码,您可能想尝试让它工作,例如,在将其增加到 200000 之前将素数增加到 100。输入一些 printlns 以​​查看您的值是什么。
  • 更新了我的代码,筛子工作了,但我得到的答案不正确,谁能帮忙?

标签: java math sieve-of-eratosthenes


【解决方案1】:

问题出在以下几行:

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

发生的情况是,有时i * i 太大以至于它绕过角落(溢出)并变成负数。 Java 没有“检查”整数数学。要解决此问题,您需要将 while 条件更改为以下

while(j &gt; 0 &amp;&amp; j &lt; array.length)

另外,您的数组大小为 200,000 而不是 2,000,000。

【讨论】:

  • 谢谢你,我现在已经修好了,返回的答案是 1997402614787,它说是不正确的。有什么想法吗?
  • @SimonKiely 我不想为你解决问题。我认为这与 ProjectEuler 的精神背道而驰。我保证当你自己解决这个问题时,你会比我更正你的代码受益更多。你很亲密。
  • 你能给我一些提示吗?我不知所措!:)
  • @SimonKiely 我将从划分问题开始。首先创建筛子,然后总结素数。这样您就可以验证您的筛子是否正确。然后验证您的求和是否有效。如果这两个都检查出来,请检查你的边缘情况。
  • @Simon Kiely,您还想将j += j 更改为j += i。这会将i 的倍数标记为合数。
【解决方案2】:

不要刻薄,但这是因为您超出了数组的范围。您对i 的限制是数组的长度,然后j 至少等于i 的平方。 j 然后被用作第 28 行要访问的数组的位置,这超出了范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多