2016-09-01 14 views
2

私は、線形再帰を使用して配列に要素を追加するJavaプログラムを作成しました。得られた出力は期待通りではありません。誰でもこのプログラムの何が間違っているのを指摘できますか?私は6として出力を期待したが得られていリニア再帰はどのように機能しますか?

public class TestSum { 

    public int count = 0; 


    public int sum(int[] a){ 

     count++; 

     if(a.length == count){ 
      return a[count -1]; 
     } 

     return sum(a) + a[count -1] ; 
    } 

    public static void main(String[] args) { 

     int[] a = {1,2,3}; 

     int val = new TestSum().sum(a); 
     System.out.println(val); 
    } 

} 

はです。なにが問題ですか?

奇妙なことに、追加の順序を変更すると、return a[count -1] + sum(a);となり、出力はとなります。

+1

"私は、加算の順番を変えると、[count -1] + sum(a)を返しても、それは6として出力されます。なぜあなたはそれを奇妙なものにしていますか? – bradimus

+0

追加の順番を変えるだけで、出力が変わるので変です。私は2 +3が3 + 2と同じであることを意味します。私は再帰についての私の理解が間違っていて、同じことを理解しようとしています。 – user001

+0

ここでは定数を追加していません。 'sum(a)'は 'count'の値を変更し、' a [count-1] 'を変更します。 – bradimus

答えて

6

一般に、再入可能ではない(つまり外部状態に依存する)再帰プログラムは不審です。あなたの特別なケースでは、countは、呼び出しをsumの間で変更し、動作をトレースするのを困難にし、最終的には観察しているエラーを引き起こします。あなたはそれを動作させるために、配列にインデックスを一緒に渡す必要があり

// The actual implementation passes the starting index 
private static int sum(int[] a, int start){ 
    if(a.length == start){ 
     return 0; 
    } 
    return sum(a, start+1) + a[start]; 
} 
// Make sure the method can be called with an array argument alone 
public static int sum(int[] a) { 
    return sum(a, 0); 
} 

方法への外部カウントをインクリメント実装とは異なり、この実装は壊すことなく、複数のスレッドで同時に呼び出すことができます。

+0

あなたの答えに同意しますが、まだカウントが外に宣言されたときにエラーが発生しやすいのはなぜですか? – user001

+0

@ user001あなた自身のメソッドの再帰的な呼び出しによってどのように変更されるのか考えずに 'count'を自由に参照することはできないためです。 'sum a(a) 'の呼び出しがあるので、' return a [count -1]; 'と' return sum(a)+ a [count -1] 'の' count-1'の値は異なります。それらの間の。これは、メソッドの外部に呼び出し状態を保持するときに注意する必要がある種類のものです。 – dasblinkenlight

関連する問題