1

私は自分がプログラミングのバックグラウンドを持っていると信じていましたが、今日、それを疑問視するものに出くわしました。コードは次のとおりです。

public class Recursive{
public static void main(String[] args) {
    func(10);        
}

static void func(int x)
{
    if(x > 0) 
    {
        func(x/2);
        System.out.print(x % 2);     // I thought the code won't reach here ever
    }                
}

}

私の意見では、このコードは何も出力しないはずです。1010しかし、コンパイルすると実際に印刷されます。System.out.print(x % 2)が以前に書かれていればfunc(X/2)意味がありますが、今は正しくないように見えます。これについての説明はありますか?

4

6 に答える 6

2

funcが呼び出され、x%2が出力されます。

一方、return func(x / 2)を使用する場合、printステートメントに到達することはありません。

于 2012-10-18T11:47:16.117 に答える
2

簡単だ。最初に、関数func()は10の値を取得します。内部的には10> 0かどうかをチェックします。そうであるため、func(5 /*10/2 = 5*/)を呼び出します。

次に、5> 0なので、内部的にfunc(2)を呼び出します。これは、.5の切り捨てによるものです。 func(2/2 /*= 1*/)が呼び出され、実行されます。次に、func(0)を呼び出します。これは戻ります。戻ると、Printステートメントは1%2 = 1で実行されます。これは内部的に戻り、printステートメントは2%2 = 0で再度実行されます。再び戻り、printステートメントは引数5%2=1で再度実行されます。最後のprintステートメントを返すと、0の印刷が再度実行されます。

于 2012-10-18T11:51:44.943 に答える
1

func への 2 番目の呼び出しを行う必要があり、その呼び出しが完了すると、スタックを下って元の関数を完成させます。

基本的な再帰理論を調べる必要があります。

http://en.wikipedia.org/wiki/Recursion_(computer_science )。

上記のように、 return func(x/2) を使用すると、その関数がスタックから削除されるため、関数の最後に到達することはありません。

于 2012-10-18T11:49:41.500 に答える
1
func(x/2);     ----------------> // Statement # 1
System.out.print(x % 2); ------> // Statement # 2

Statement # 2atUnreachable Blockの値を返せばよかったでしょうfunc(x / 2) callStatement # 1

Recursive function callsに保存されstackます。そのため、呼び出しごとに astack entryが作成され、現在の呼び出しが保存され、次の呼び出しに向けて移動します。

ここで、基本条件に達すると、関数の前の状態をポップすることによって がstack開始されroll-back、最終的に開始した場所に到達します。

すべてのfunc呼び出しがスタックからポップされた後function、最後のfunc()呼び出しが行われた場所の次のステートメントで実行が続行され(Statement # 2 in this case)、完了後、その関数が返され、スタック上の次の関数が呼び出されます。(注: -return func(x / 2)の代わりに を使用しfunc(x / 2)た場合、コードは次のステートメントを実行せず、すぐにスタック内の次の関数に制御を渡します。したがってUnreachable Code)

というわけで最後に発言

System.out.print(x % 2);

が完全に空になると実行され、stack制御が

func(x / 2)

スタックの一番下にあった関数呼び出し。


したがって、再帰は次のようになります。

スタック: -

func(x / 8)  --> Base condition
func(x / 4)  ^
func(x / 2)  ^
func(x)      --> First invocation

が基本x / 8条件であるとします。したがって、実行がfunc(x / 8)完了すると、実行される次のステートメントは次のようになります。

System.out.println(x % 2)-> ここで x の値はoriginal-x / 8

次に、この関数がスタックからポップされ、スタック内の次の関数に制御が返されます: - func(x / 4)。次に、次のステートメントが実行されます: -

System.out.println(x % 2)-> またxこちらoriginal-x / 4

等々。そして最終的に、System.out.println(x % 2)実行されますoriginal-x

于 2012-10-18T12:01:29.790 に答える
1

1 と 0 を出力する動作は完全に正しいものです。

x> は厳密に 0 より大きいですが、x は整数であるため、新しい x = int(x/2) を使用して再帰をさらに深くします。

x<=1 の場合、x/2==0 になるため、再帰が停止し、x/2 の残りの出力が開始されます。

あなたの場合:

f(10)->f(5)->f(2)->f(1)->f(0)  
                          |
  0 <-  1  <- 0  <-  1  <-+  

ヒント: この種の問題が発生した場合は、フローを理解するために System.out.println() トレースをコードに入れます。Eclipse/Netbeans/Idea を使用している場合は、デバッグ モードにしてコードをステップインできます。

于 2012-10-18T12:39:10.197 に答える
0

うーん、一見何も表示されないと思いましたが、トレース コードから、x の値を変更することは決してないため、1010 が書き込み応答であることがわかりました。つまり、x に対して操作を行っていますが、保存しているので、代わりに 1010 です。何もない。

いいひっかけ問題

于 2012-10-18T12:04:23.787 に答える