【问题标题】:BitSet(JAVA) is throwing outofBoundsException in the implementation of Sieve Of EratosthenesBitSet(JAVA) 在 Sieve Of Eratosthenes 的实现中抛出 outofBoundsException
【发布时间】:2013-11-19 10:09:44
【问题描述】:

这是我执行 Sieve Of Eratosthenes 的函数,

void solve() throws IOException {

    int n = 200000;

    ArrayList<Integer> primes = new ArrayList<Integer>();
    BitSet bs = new BitSet(n + 1);

    for(int i = 0; i <= n + 1; i++)
        bs.set(i);

    //setting bits at 0 and 1 to 0, since these are not considered as primes
    bs.clear(0);
    bs.clear(1);

    for(int i = 2; i <= n + 1; i++) {
        if(bs.get(i)) {
            //cross out multiples of i starting from i*i (lesser one would have always been crossed out)
            for(int j = i*i; j <= n + 1; j += i)
                {
                    bs.clear(j);
                }

            primes.add(i);          //add this prime to the list

        }
    }

    for(int e : primes)
        out.println(e);
}

当我运行这个时,我在内部 for 循环中得到了 arrayOutOfBoundsException,即

for(int j = i*i; j <= n + 1; j += i)
{
  bs.clear(j);            //EXCEPTION is raised here
}

我得到的错误信息是:

Exception in thread "main" java.lang.IndexOutOfBoundsException: bitIndex < 0: -2146737495
at java.util.BitSet.clear(BitSet.java:532)
at ERATOSTHENES.solve(ERATOSTHENES.java:45)

我不明白问题出在哪里,如果我将 n 减少到 20000,那么我的代码可以正常工作,但是在 n = 168000(大约)之后,它会显示这个 OutofBoundsException。

它是 BitSet 特有的东西,我没有得到的一些属性吗?

【问题讨论】:

    标签: java indexoutofboundsexception bitset sieve-of-eratosthenes


    【解决方案1】:

    您正在(在最坏的情况下)将变量 i 初始化为接近 200,000 的大数(特别是大素数?)。这意味着初始化为i * ij将超过40,000,000,000,这大大超过int的最大值(大约2,147,000,000)这意味着它们将溢出到负值,这肯定会超出范围。

    要解决这种情况下的问题,请将变量声明为 long 类型,它是 64 位的,可以容纳更大的值。

    【讨论】:

    • 是的,但是要访问 BitSet,您需要整数值索引,因此,即使您声明变量,只要您仍然必须将其转换为 int。不确定这是否能解决问题。但是 cast 会改变超过 32 位数字的长值
    【解决方案2】:

    你在这一行得到一个整数溢出(i*i 是负数):

    for(int j = i*i; j <= n + 1; j += i)
    

    例子:

    System.out.println(168000 * 168000);
    

    打印:

    -1840771072
    

    这是负数,所以小于n + 1并通过循环条件。

    【讨论】:

      【解决方案3】:

      我认为这可能是因为您使用的是 int 并且数字变得太大,即

      200,000 * 200,000 是一个巨大的数字,应该是一个很长的数字。

      【讨论】:

      • 在这种情况下不要使用 double,您需要精确的值。坚持很久。
      猜你喜欢
      • 1970-01-01
      • 2012-02-21
      • 2018-08-10
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-14
      相关资源
      最近更新 更多