1

整数の桁数の合計を計算する関数を作成しました。コードを短くしようとして、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));

}
4

9 に答える 9

4

戻ることはありませんが、どんどん深く再帰します。

return ステートメントはありますが、返す前に、n%10+sumDigits(n/10)無限再帰を含む式の値を計算する必要があります。

注意: 関数をそれ自体から呼び出すたびに、関数のコンテキスト (ローカル変数) がスタックの一番上に追加されます。スタックのサイズには制限があります。最終的にそのサイズに達すると、その状態でスローされるエラーが StackOverflowError になります。

于 2013-05-06T13:17:03.673 に答える
3

それは停止節がないからです。sumDigitsあなたは永遠に呼び出すでしょう。

于 2013-05-06T13:16:33.470 に答える
3

再帰関数は、終点により近い値に対するその操作の関数として操作を表現するものとして定義できます。

したがって、すべての再帰関数には、ある時点で終了条件が必要です。そうしないと、無限繰り返されます (より正確には、スタックを吹き飛ばすまで)。

「桁の合計」再帰的方法の基本的な定義 ( の負でない値の場合n) は次のとおりです。

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

その最初のビットである終了条件は非常に重要であり、何らかの理由でコメントアウトしているようです。

于 2013-05-06T13:21:33.553 に答える
2

その行を削除すると、再帰には基本ケースがなくなります。つまり、戻りません。

于 2013-05-06T13:16:31.473 に答える
2

プログラムに割り当てられたメモリ内のアドレス スタックが新しいアドレスを格納できない場合は常に、スタック オーバー フロー エラーが発生します。

そのため、システムを再帰的に呼び出すとsumDigits()、最後に追跡されたものを LIFO 方式で保存し続けます。これにより、システムが以前のアドレスに簡単に戻ることができます。これは再帰に必要です。

再帰を無限に行うか、メモリの制約を超えて行うと、stackOverflow エラーが発生します。

于 2013-05-06T13:23:10.553 に答える
2

コメントアウトしたステートメントは、この再帰関数の基本ケースです。基本ケースがないと、この関数は無限にループします。


メイン メソッドの例を実行すると、次のよう に
なり
ます 。 = 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 のときに返されるため、この状況を回避できます。

于 2013-05-06T13:33:19.280 に答える
1

再帰には終了条件がありません。そうでなければ、再帰関数を何度も呼び出すと、最終的にstackはオーバーフローします

于 2013-05-06T13:18:02.810 に答える
0

停止条件のコメントを外します。

于 2013-05-06T13:18:33.670 に答える