【问题标题】:Sieve of Atkin returns array... with invalid indices - Java阿特金筛子返回数组......具有无效索引 - Java
【发布时间】:2012-06-25 19:16:20
【问题描述】:

所以我做了一个sieve of Atkin 算法来生成素数(用于欧拉计划问题)。它返回一个名为 primes 的素数数组 (int[])。问题是,每当我尝试从某个索引访问该数组时(我在我的 main 方法中这样做),它都会抛出一个 java.lang.ArrayIndexOutOfBounds 异常。请帮忙(如果您认为我的逻辑与仙女不符,并且有更简单的方法可以做到这一点,请告诉我)!

import java.lang.*;
import java.util.*;

public class SieveOfAtkin {
    public static void main(String[] stuff) {
        int limit = getInt("Limit?");
        int[] p = getPrimes(limit);
        for(int i = 0; i < p.length; i++) {
            System.out.println(p[i]);
        }
    }
    public static int[] getPrimes(int limit) {
        boolean[] isPrime = new boolean[limit + 1];
        double sqrt = Math.sqrt(limit);
        int n = 0;
        for(int i = 0; i < limit + 1; i++) {
            isPrime[i] = false;
        }
        for(int x = 0; x < sqrt; x++) {
            for(int y = 0; y < sqrt; y++) {
                n = 4 * x * x + y * y;
                if(n <= limit && (n % 12 == 1 || n % 12 == 5)) {
                    isPrime[n] = !isPrime[n];
                }
                n = 3 * x * x + y * y;
                if(n <= limit && n % 12 == 7) {
                    isPrime[n] = !isPrime[n];
                }
                n = 3 * x * x - y * y;
                if(n <= limit && n % 12 == 11 && x > y) {
                    isPrime[n] = !isPrime[n];
                }
            }
        }
        for(int i = 5; i < sqrt; i++) {
            if(isPrime[i]) {
                for(int j = i * i; j < limit; j = j + (i * i)) {
                    isPrime[j] = false;
                }
            }
        }
        int count = 0;
        for(int i = 0; i < isPrime.length; i++) {
            if(isPrime[i]) {
                count++;
            }
        }
        int[] primes = new int[count];
        int found = 0;
        if (limit > 2) {
            primes[found++] = 2;
        }
        if (limit > 3) {
            primes[found++] = 3;
        }
        for (int p = 5; p <= limit; p += 2) {
            if (isPrime[p]) {
                primes[found++] = p;
            }
        }
        return primes;
    }
public static int getInt(String prompt) {
    System.out.print(prompt + " ");
    int integer = input.nextInt();
    input.nextLine();
    return integer;
}
}

【问题讨论】:

  • 您的代码链接不指向任何 Java 代码。请在问题中包含一个简短但完整的程序。
  • 请注意,您提供的代码也无法编译。为什么不只使用命令行参数?将第一行更改为 int limit = Integer.parseInt(stuff[0]); 并摆脱您的 getInt 方法。
  • 我试过了,它给了我另一个 arrayindexoutofbounds 异常。如何将 stuff[0] 设置为我的号码?
  • 没关系,I got it

标签: java indexoutofboundsexception sieve-of-atkin


【解决方案1】:

没有“具有无效索引的数组”之类的东西。如果您正在访问该数组并且您得到一个ArrayIndexOutOfBounds,那么您使用的是负索引或者该数组没有您想象的那么大。调试您的代码以找出数组的实际长度(使用array.length)并将其与您预期的长度进行比较。

编辑:好的,现在我们得到了代码,我们可以看到哪里出了问题。当您计算出数组的大小时,您并没有计算值 2 和 3 - 但是当您填写 primes 时,您正在使用它们。因此primes 是两个太短的值。

您可以通过将isPrime[2]isPrime[3] 设置为true 来解决此问题。然后,您不需要之前检查 limit &gt; 2 等 - 只需遍历整个 primes

// After removing the special cases for 2 and 3 before this loop... but setting
// isPrime[2] and isPrime[3] to true
for (int p = 2; p <= limit; p++) {
    if (isPrime[p]) {
        primes[found++] = p;
    }
}

【讨论】:

  • 好的,我上传了代码。我让我的程序告诉我count 变量的大小,也就是数组的长度,即 24。所以我不知道为什么它给了我一个无效的索引,尤其是如果访问它的循环是for(int i = 0; i &lt; p.length; i++)(p 是我的数组)。
  • 您可以尝试将该语句切换到 for(int prime : p) System.out.println(prime);在循环。这将保证它只会打印有效的引用。
  • @Bluefire:这不是引发异常的部分。您需要注意堆栈跟踪。看看我的编辑出了什么问题。
  • 好的,谢谢!经过这里和那里的一些曲折,它完美地工作了!
【解决方案2】:

您的问题是您在 isPrime 数组中将 1 标记为素数,而不是 2 和 3,因此当您计算素数时,您的计数会减一。然后,当您开始填充素数数组时,您不会检查素数 2 和 3 的 isPrimes 数组,而是假设它们已被正确计算并在您的素数数组中标记它们,然后开始添加其余素数(现在是一个太多了)。

如果您在循环中添加一些调试,计算素数的数量并填充素数数组,您应该很容易找到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多