我正在使用Eratosthenes的Sieve解决Sphere的在线评判Prime Generator。
我的代码适用于所提供的测试用例。但是......正如问题明确指出:
输入以数字t开头 测试用例在一行中(t <= 10)。 在接下来的每一行中都有 两个数m和n( 1 <= m <= n <= 分开的1000000000,n-m <= 100000) 一个空间。
我知道方法Integer.parseInt()
在处理非常大的数字时抛出异常,并且在线判断表明正在抛出异常,所以我将parseInt
的每个案例都更改为{{1}在我的代码中。
嗯,在Netbeans 6.5上运行正常,m和n的值很小。
parseLong
输入+输出:
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("");
}
}
}
但JCreator LE正在这样说:
run:
2
1 10
2
3
3
5
7
3 5
3
5
BUILD SUCCESSFUL (total time: 11 seconds)
这里我没有整数溢出,但为什么jcreator会抱怨?
考虑到临界测试用例,该程序也会破坏Netbeans:
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.
如何处理问题陈述中那些巨大的整数?
编辑:根据建议我更改了BitSet的布尔数组,但我仍然得到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
:
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("");
}
}
}
答案 0 :(得分:6)
这是你的问题:
boolean[] isComposite = new boolean[(int)upperBound + 1];
这将使用大量空间,因为它为每个布尔值分配4个字节,以便更快地访问。使用java.lang.BitSet来避免这种情况。
最终,您的数字可能会长得太长,您将不得不使用BigInteger。但在那时,Eratosthenes的筛子可能不会再削减它了。
答案 1 :(得分:1)
你正在用很多空间存放你的布尔值。您可能会尝试将每个布尔值压缩为一位。考虑一下,你是否真的需要为下限和上限之间的每个数字设置一个布尔值?例如,偶数从不是素数(2除外),也不是3的倍数(除了3)等等。This page可能会给你一些好的想法。
答案 2 :(得分:1)
您的BitSet实施中存在一个小错误。这一行:
isComposite.set(m);
实际应该是:
isComposite.set(k);
修复该行后,代码在测试用例999900000到1000000000上运行无错误,从999900017开始吐出4,832个素数,以999999937结束.BitSet使用125 MB内存,该方法需要17秒才能运行我的2.2 GHz笔记本电脑。
答案 3 :(得分:0)
你是否使用BigInteger类?因为如果没有,我强烈推荐这里。它将处理您描述的大数字。如果这还不够好,那么您需要通过将-Xmx作为命令行参数来为JVM分配更多内存。这里有一个例子:
http://www.coderanch.com/t/384456/Java-General-intermediate/java/Increase-JVM-heap-size-eclipse
如果您还需要十进制数字,那么还有一个BigDecimal。
答案 4 :(得分:0)
由于Java堆大小的限制,我遇到了类似的问题。而不是使用高内存整数,转换为布尔值解决了问题。 找到附加的代码:
24 = 7 + 7 + 10