我有一段代码,但我不明白为什么它会在线程“main”java中给我带来异常。lang.Stackoverflowerr。
问题是:
Given a positive integer n, prints out the sum of the lengths of the Syracuse
sequence starting in the range of 1 to n inclusive. So, for example, the call:
lengths(3)
will return the the combined length of the sequences:
1
2 1
3 10 5 16 8 4 2 1
which is the value: 11. lengths must throw an IllegalArgumentException if
its input value is less than one.
我的代码:
import java.util.HashMap;
public class Test {
HashMap<Integer,Integer> syraSumHashTable = new HashMap<Integer,Integer>();
public Test(){
}
public int lengths(int n)throws IllegalArgumentException{
int sum =0;
if(n < 1){
throw new IllegalArgumentException("Error!! Invalid Input!");
}
else{
for(int i =1; i<=n;i++){
if(syraSumHashTable.get(i)==null)
{
syraSumHashTable.put(i, printSyra(i,1));
sum += (Integer)syraSumHashTable.get(i);
}
else{
sum += (Integer)syraSumHashTable.get(i);
}
}
return sum;
}
}
private int printSyra(int num, int count){
int n = num;
if(n == 1){
return count;
}
else{
if(n%2==0){
return printSyra(n/2, ++count);
}
else{
return printSyra((n*3)+1, ++count) ;
}
}
}
}
驱动代码:
public static void main(String[] args) {
// TODO Auto-generated method stub
Test s1 = new Test();
System.out.println(s1.lengths(90090249));
//System.out.println(s1.lengths(5));
}
.我知道问题在于递归。如果输入值很小,则不会发生错误,例如:5。但是当这个数字很大时,比如90090249,我在线程“main”java中遇到了一个例外。lang.Stackoverflowerr。谢谢大家的帮助。:)
我差点忘了错误消息:
Exception in thread "main" java.lang.StackOverflowError
at Test.printSyra(Test.java:60)
at Test.printSyra(Test.java:65)
at Test.printSyra(Test.java:60)
at Test.printSyra(Test.java:65)
at Test.printSyra(Test.java:60)
at Test.printSyra(Test.java:60)
at Test.printSyra(Test.java:60)
at Test.printSyra(Test.java:60)
一种解决方案是允许JVM使用java-Xss参数为堆栈递归占用更多空间。它的默认值是小于1MB的IIRC,最多可以限制为几百个递归。
更好的解决方案是重写练习而不递归:
private int printSyra(int num){
int count = 1;
int n = num;
while(n != 1){
if(n%2==0){
n = n/2;
++count;
}
else{
n=(n*3)+1;
++count;
}
}
return count;
}
这是递归算法固有的问题。让递归的数量足够大,你就无法真正避免堆栈溢出,除非该语言能够保证尾部调用优化(Java和大多数类似C的语言都不能保证)。真正修复它的唯一方法是“展开”递归,迭代或使用辅助函数重写算法,以模拟递归调用的状态传递,而无需实际嵌套调用。
你的算法很好。但是,int
对于您的计算来说太小了,因此输入失败:
printSyra(113383, 1);
在某个时候整数溢出为负值,您的实现变得疯狂,无限递归。将int num
更改为long num
,您会没事的-一段时间。稍后您将需要BigInteger
。
请注意,根据维基百科关于Collatz猜想(粗体矿):
对于任何小于1亿的初始起始数,最长的级数为63728127,共949步。对于小于10亿的起始数字,它是670617279,包含986个步骤;对于小于100亿的数字,它是9780657630,包含1132个步骤。
总步数相当于您可以期望的最大嵌套级别(堆栈深度)。因此,即使是相对较大的数字StackOverflow Error
也不应该发生。使用BigInteger
查看此实现:
private static int printSyra(BigInteger num, int count) {
if (num.equals(BigInteger.ONE)) {
return count;
}
if (num.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) {
return printSyra(num.divide(BigInteger.valueOf(2)), count + 1);
} else {
return printSyra(num.multiply(BigInteger.valueOf(3)).add(BigInteger.ONE), count + 1);
}
}
它甚至适用于非常大的价值:
printSyra(new BigInteger("9780657630"), 0) //1132
printSyra(new BigInteger("104899295810901231"), 0) //2254
代码重构后,我在尝试编译Maven项目时遇到以下错误: 我尝试删除文件夹但问题未解决。您知道如何解决此问题吗?
我有任务要做,我有一个问题,我得到了错误。我不知道怎么修理它: 线程“main”java.lang.NullPointerException在test.main(test.java:29)中出现异常
我在线程“main”java中遇到异常。错误:未解析编译。 我做错了什么? 线程“main”中出现异常: java.lang.错误:未解决的编译问题: 对于类型在
我有任务要做,我有一个问题,我得到了错误。我不知道如何修理它: 异常线程"main"java.lang.NullPointerExcema在test.main(test.java:29) 这是我的密码:
我从GitHub克隆了我的项目,现在我无法运行我的项目。 我收到以下错误: 知道是什么导致了这个错误吗? 编辑 我检查了这个问题Intellij在我发布到这里之前突然抛出ClassNotFoundException,它没有给我任何解决方案...为什么要将我的问题标记为重复,因为那个问题不能解决我的问题?
我得到了这个错误: 线程“main”Java.lang.NosuchFielderRror:calificacion.main处的num1异常(problema_3.Java:17) 在这个简单的终端Java程序上键入第一个值后: 另一方面,这一个运行良好,我使用相同的输入法在这两个: 提前道谢。