[英]Why do i get a StackOverflowError
我做了一個函數,可以計算整數的總和。 為了使代碼更短,我在if語句中添加了注釋,以查看它是否仍然有效,因此可以將其刪除,但出現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));
}
它永遠不會返回,而只會遞歸越來越深。
您確實有一個return語句,但是在返回之前需要計算表達式n%10+sumDigits(n/10)
的值,該值涉及無限遞歸。
注意:每次您從自身調用函數時,函數的上下文(局部變量)都會添加到堆棧頂部。 堆棧的大小有限。 最終,您達到該大小,而StackOverflowError是在這種情況下引發的錯誤。
那是因為沒有stop子句。 您將永遠調用sumDigits
。
可以將遞歸函數定義為在更接近端點的值上將操作表示為該操作的函數。
因此,每一個遞歸函數需要在某些時候結束條件,否則會無限復發(或者,更准確地說,直到你吹你的堆棧)。
“數字和”遞歸方法的基本定義(對於n
非負值)是:
def sumOfDigits (n):
if n < 10:
return n
return (n % 10) + sumOfDigits (n / 10) # assumes integer division.
最后一點,即結束條件,非常重要,由於某種原因,您似乎已將自己的注釋掉了。
如果刪除該行,則遞歸不再具有基本情況,這意味着它永遠不會返回。
每當為程序分配的內存中的地址堆棧無法存儲任何新地址時,就會發生stackover流錯誤。
因此,當您遞歸調用sumDigits()
,系統會繼續以LIFO方式保存最后跟蹤的內容。 因此系統很容易返回到先前的地址,這對於遞歸來說是必須的。
如果無限期地執行遞歸操作或超出內存限制,則會遇到stackOverflow錯誤。
您注釋掉的語句是此遞歸函數的基本情況。 沒有基本情況,此函數將無限循環。
在main方法中計算示例時,您將獲得:
sumDigits(12611)
= 1 + sumDigits(1261)
= 1 +(1 + sumDigits(126))
= 1 +(1 +(6 + sumDigits(12)))
= 1 +(1 +(6 +(2 + sumDigits(1))))
= 1 +(1 +(6 +(2 +(1 + sumDigits(0)))))//至此注釋掉if語句將返回
= 1 +(1 +(6 +(2 +(1 +(0 + sumDigits(0))))))
= 1 +(1 +(6 +(2 +(1 +(0 +(0 + sumDigits(0))))))))
...
此時,程序陷入了無限循環。 當n為1時,已注釋掉的語句將返回,從而避免了這種情況。
因為您正在從自身調用sumDigits()
,所以應該使您從無限遞歸返回的代碼已被注釋掉。 取消注釋行if(n%10==n){ return n;}
您的遞歸沒有終止條件。 否則,您一遍又一遍地調用遞歸函數,最終stack
將溢出
取消注釋您的停止條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.