2016-10-19 37 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時,它會翻轉。你不應該在循環條件中允許相等。