3

私はエラトステネスのふるいを使ってスフィアのオンラインジャッジプライムジェネレーターを解いています。

私のコードは、提供されたテストケースで機能します。しかし..問題が明確に述べているように:

入力は、1行のテストケースの数tから始まります(t <= 10)。次のt行のそれぞれに、スペースで区切られた2つの数値mとn( 1 <= m <= n <= 1000000000、nm <= 100000)があります。

非常に大きな数を処理するときにメソッドInteger.parseInt()が例外をスローし、オンラインジャッジが例外がスローされていることを示していたので、コード内のすべてのケースparseIntをに変更しました。parseLong

さて、mとnの値が小さいNetbeans6.5では問題なく動作しています。

package sphere;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main{

public static void runEratosthenesSieve(long lowerBound, long upperBound) {

      long upperBoundSquareRoot = (long) Math.sqrt(upperBound);

      boolean[] isComposite = new boolean[(int)upperBound + 1];

      for (int m = 2 /*int m = lowerBound*/; m <= upperBoundSquareRoot; m++) {

            if (!isComposite[m]) {

                if (m>=lowerBound) {System.out.println(m);}

                  for (int k = m * m; k <= upperBound; k += m)

                        isComposite[k] = true;

            }

      }

      for (int m = (int)upperBoundSquareRoot; m <= upperBound; m++)

            if (!isComposite[m])

                 if (m>=lowerBound){ System.out.println(m);}

}

public static void main(String args[]) throws java.lang.Exception{

       BufferedReader r = new BufferedReader(new InputStreamReader(System.in));


       String l = r.readLine();

       int testCases = Integer.parseInt(l); 

       for (int i =0; i<testCases; i++){
       String s =r.readLine();

       String []splitted=s.split(" ");


       long lowerBound = Long.parseLong (splitted[0]);
       long upperBound = Long.parseLong(splitted[1]);

       runEratosthenesSieve (lowerBound,upperBound);

       System.out.println("");
       }
}

}

入力+出力:

run:
2
1 10
2
3
3
5
7

3 5
3
5

BUILD SUCCESSFUL (total time: 11 seconds)

しかし、JCreatorLEはこれを言っています:

2
1 10
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
    at java.lang.Long.parseLong(Long.java:424)
    at java.lang.Long.parseLong(Long.java:461)
    at sphere.Main.main(Main.java:51)

Process completed.

ここでは整数のオーバーフローはありませんが、なぜjcreatorが文句を言うのでしょうか。

境界テストケースを考慮すると、プログラムはNetbeansにも影響を及ぼします。

run:
2
999900000 1000000000 
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at sphere.Main.runEratosthenesSieve(Main.java:13)
        at sphere.Main.main(Main.java:55)
Java Result: 1

問題ステートメントのこれらの巨大な整数をどのように処理できますか?

編集:提案により、BitSetのブール配列を変更しましたが、まだOutOFMemoryError:を取得しています。

package sphere;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.BitSet;

public class Main{

public static void runEratosthenesSieve(long lowerBound, long upperBound) {

      long upperBoundSquareRoot = (long) Math.sqrt(upperBound);

      //boolean[] isComposite = new boolean[(int)upperBound + 1];

      BitSet isComposite = new BitSet((int)upperBound+1);

      for (int m = 2 /*int m = lowerBound*/; m <= upperBoundSquareRoot; m++) {

            if (!isComposite.get(m)) {

                if (m>=lowerBound) {System.out.println(m);}

                  for (int k = m * m; k <= upperBound; k += m)

                        isComposite.set(m);

            }

      }

      for (int m = (int)upperBoundSquareRoot; m <= upperBound; m++)

            if (!isComposite.get(m))

                 if (m>=lowerBound){ System.out.println(m);}

}

public static void main(String args[]) throws java.lang.Exception{

       BufferedReader r = new BufferedReader(new InputStreamReader(System.in));


       String l = r.readLine();

       int testCases = Integer.parseInt(l); 

       for (int i =0; i<testCases; i++){
       String s =r.readLine();

       String []splitted=s.split(" ");


       long lowerBound = Long.parseLong (splitted[0]);
       long upperBound = Long.parseLong(splitted[1]);

       runEratosthenesSieve (lowerBound,upperBound);

       System.out.println("");
       }
}

}

入出力:

run:
1
999900000 1000000000
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.BitSet.initWords(BitSet.java:144)
        at java.util.BitSet.<init>(BitSet.java:139)
        at sphere.Main.runEratosthenesSieve(Main.java:16)
        at sphere.Main.main(Main.java:58)
Java Result: 1
BUILD SUCCESSFUL (total time: 14 seconds)
4

5 に答える 5

6

これがあなたの問題です:

boolean[] isComposite = new boolean[(int)upperBound + 1];

これは、より高速なアクセスを可能にするためにブール値ごとに4バイトを割り当てるため、膨大な量のスペースを使用します。これを回避するには、 java.lang.BitSetを使用します。

最終的には、数値が長くなりすぎる可能性があり、BigIntegerを使用する必要があります。しかし、その時点で、エラトステネスのふるいはおそらくそれをもう切ることはないでしょう。

于 2009-07-03T05:56:56.940 に答える
1

ブール値を格納するために多くのスペースを使用しています。すべてのブール値を 1 ビットに絞り込もうとするかもしれません。考えてみてください。下限と上限の間のすべての数値にブール値が本当に必要ですか? たとえば、偶数は決して素数ではなく (2 を除く)、すべてが 3 の倍数でもありません (3 を除く) などです

于 2009-07-03T13:18:17.147 に答える
1

BitSet の実装に小さなバグがありました。この線:

                    isComposite.set(m);

実際には次のようにする必要があります。

                    isComposite.set(k);

その行を修正すると、コードは 999900000 から 1000000000 までのテスト ケースでエラーなしで実行され、999900017 で始まり 999999937 で終わる 4,832 個の素数が吐き出されました。 BitSet は 125 M バイトのメモリを使用し、私の 2.2 GHz でメソッドを実行するのに 17 秒かかりました。ラップトップ。

于 2016-05-01T01:59:11.563 に答える
0

BigIntegerクラスを使用していますか?いいえの場合は、ここで強くお勧めします。それはあなたが説明している大きな数字を扱います。それでも不十分な場合は、コマンドラインパラメータとして-Xmxを実行して、JVMが使用するメモリをさらに割り当てる必要があります。ここに例があります:

http://www.coderanch.com/t/384456/Java-General-intermediate/java/Increase-JVM-heap-size-eclipse

10進数も大きくする必要がある場合は、BigDecimalもあります。

于 2009-07-03T05:47:39.920 に答える