2016-10-19 36 views
-1

我有一个简单的Java方法,它假设计算一定数量的素数列表。这个Java函数为什么会崩溃?

public class Factors { 



public static List<Integer> fac(List<Integer> factors, int number) { 
    if(number < 2) { 
     throw new IllegalArgumentException("Number must be greater than one"); 
    } 


    for (int i = 2; i <= number; i++) { 
     while (number%i == 0) { 
      factors.add(i); 
      number /= i; 
     } 
    } 
    return factors; 
} 
public static void main(String [] args) 
{ 
final long startTime = System.currentTimeMillis(); 

    ArrayList<Integer> factors = new ArrayList<>(); 
    System.out.println(fac(factors, 2147483647)); 

final long endTime = System.currentTimeMillis(); 
System.out.println("Total execution time: " + (endTime - startTime)); 
} 
} 

这段代码工作正常,除非您将Integer.MAX_VALUE加入它;在这种情况下给:
java.lang.OutOfMemoryError:Java堆空间
最初,我想,这是因为,ArrayList初始化是在一个方法内,但在删除后,同样的错误仍然存​​在。
此外,这样的:

public static List<Long> facrec2(List<Long> list, long number) { 
    if (number < 2) { 
     return list; 
    } 

    if (number == 2) { 
     list.add(2L); 
     return list; 
    } 

    for (long i = 2; i <= number; i++) { 
     while (number % i == 0) { 
      number /= i; 
      list.add(i); 
      return facrec2(list, number); 
     } 
    } 
    return null; 
} 

方法适用于最大值(改变签名整数后,适用于整数最大值太)。两者的逻辑假设是一样的,只有递归执行的第二个使得区别...

+0

+1。我认为你可以在调试方面做得更好(或者至少可以证明你的调试),但是这个bug如何导致这个异常是令人惊讶的微妙。 – ruakh

+0

是的,但我从其他人那里获得了这两个功能,只是作为一个例子,并且不耐烦地发布在stackoverflow上,而不是让自己工作:) –

+0

'[对任何给定的审判除数的迭代和递归处理应该]的逻辑是与递归相同,在发现'i'之后,你_never_开始增加(并重新检查)'i',将'number'剩下的部分分开。 – greybeard

回答

1
for (int i = 2; i <= number; i++) { 

问题在这里。如果number == Integer.MAX_VALUE这个循环将永远不会终止。一旦i得到Integer.MAX_VALUE,下一个增量将其设置为Integer.MIN_VALUE,这是非常负面的,并且循环继续执行,因此您将永远添加到列表并耗尽内存。

的最简单的解决方案是改变循环条件<和处理其中number仍然分别具有其原始值的情况下(即,其中是number素的情况下)。您也可以退出循环一次number == 1

+1

+1。请注意,当'i'达到'Integer.MAX_VALUE'时,'数字'被设置为'1';但由于'i'在之后立即被设置为'Integer.MIN_VALUE',它仍然保持小于'number'。然后'i'最终达到'1',此时'number%i == 0'永远为真,因此列表中会被任意多个'1'填充,直到内存用完。 “Integer.MAX_VALUE”碰巧是主要的,这真是糟糕。 :-) – ruakh

+0

是的,正是发生了这种情况。第一个函数改变时,如果产量[2147483647,-1],但给出了错误的答案,例如,120返回2,3,4,5(4不是质数)。所以虽然重要,并且您提议的功能需要修复。第二个似乎很好。 –

+0

现在删除的提议的“while/if”更改不是我自己,是不正确的。你需要'while'来获得主要因素。 – EJP

0

此循环从不终止。当计数器达到Integer.MAX_VALUE时,它会翻转。你不应该在循环条件中允许相等。