2013-05-06 107 views
1

我做了一個函數,計算一個整數的數字的總和。試圖使代碼更短,我把評論if語句,看看是否仍然有效,所以我可以刪除它,但我得到StackOverflowError,爲什麼? 這是我的代碼:爲什麼我得到一個StackOverflowError

public static int sumDigits(int n) { 


    //if(n%10==n){ return n;} 

     return n%10+sumDigits(n/10); 

    } 

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    System.out.println(sumDigits(12611)); 

} 
+1

這很簡單:你得到一個StackOverflowError,因爲堆棧溢出。 – Ingo 2013-05-06 13:18:02

+1

考慮一下:「1.呼吸,2.從本清單開始重新開始」。你什麼時候會停止呼吸? – 2013-05-06 13:18:24

+3

這是一個經典的例子,如何強制stackoverflowexception,無限遞歸 – 2013-05-06 13:19:07

回答

4

它從不返回,但只是遞歸更深入。

您確實有return語句,但在返回之前,需要計算表達式n%10+sumDigits(n/10)的值,該值涉及無限遞歸。

注意:每次從本身調用函數時,函數的上下文(局部變量)都會添加到堆棧頂部。該堆棧的大小有限。最終你達到這個大小,StackOverflowError是在這種情況下拋出的錯誤。

2

如果去掉那行,你recursion不具備基本情況下去,這意味着它永遠不會返回。

3

這是因爲沒有停止條款。你將永遠調用sumDigits

1

因爲您從本身調用sumDigits()並且應該導致您從無限遞歸返回的代碼被註釋掉。取消註釋行if(n%10==n){ return n;}

1

您的遞歸沒有終止條件。否則,您一次又一次地調用遞歸函數,最終stack將溢出

0

取消註釋停止條件。

3

遞歸函數可以定義爲表示一個操作作爲該操作對更接近終點的值的函數。

因此,每一個遞歸函數需要在某些時候結束條件,否則將復發無限(或者,更準確地說,直到你吹你的堆棧)。

的「數字之和」遞歸方法的基本定義(爲n非負值)爲:

def sumOfDigits (n): 
    if n < 10: 
     return n 
    return (n % 10) + sumOfDigits (n/10) # assumes integer division. 

即第一位,結束條件,是非常重要的,你似乎出於某種原因已經評論過你。

2

只要分配給程序的內存中的地址堆棧無法存儲任何新地址,就會發生stackover流程錯誤。

所以當你遞歸調用sumDigits()時,系統繼續保存上次跟蹤的LIFO方式。因此係統很容易回到以前的地址,這是遞歸必須的。

如果無限遞歸或高於內存約束,您將遇到stackOverflow錯誤。

1

您註釋掉的語句是這個遞歸函數的基本情況。沒有基本的情況下,這個函數將無限循環。


當在主方法制定出例如,你可以獲得:
sumDigits(12611)
= 1個+ sumDigits(1261)
= 1 +(1個+ sumDigits(126))
= 1 +(1+(6 + sumDigits(12)))
= 1+(1+(6+(2 + sumDigits(1))))
= 1+ (1 + sumDigits(0)))))//此時註釋掉if語句將返回
= 1 +(1 +(6 +(2 +(1 +(0 + sumDigits(0))) )))
= 1 +(1 +(6 +(2 +(1 +(0 +(0 + sumDigits(0)))))))
...

此時程序陷入了無限循環。當n爲1時,註釋掉的語句會返回,從而避免了這種情況。

相關問題