web-dev-qa-db-ja.com

フィボナッチシリーズで再帰を理解する

私は再帰とreturnステートメントがどのように機能するかをよりよく理解しようとしています。そのため、特定の用語に関連付けられたフィボナッチ数(この場合は4)を識別するためのコードを調べています。elseステートメントを理解するのが困難です。

def f(n):
  if n == 0:
    return 0
  if n == 1:
    return 1
  else:
    return f(n-1) + f(n-2)

f(4)

Visualize Python=を使用して、各ステップで何が起こるかを調べてみましたが、elseステートメントにヒットすると迷ってしまいます。

それは、nの値を取り、1を引いて、関数定義に返す新しいn値3を作成するように見えます。したがって、elseステートメントの最初の関数からの値のみを返すように見えます。しかし、elseステートメントは2つの関数の合計を返すように記述されていますf(n-1) + f(n-2)この場合、戻り値は5になると思いますか? 2つの関数を一緒に追加することもできますか?

よろしくお願いします。

これはVisualizeのコードへのリンクですPython Sum of 2 functions

13
efw

疑わしいときは、それを分解してください。

enter image description here

ツリーフローは実際には実際の制御フローに直観的ではありませんが、呼び出しのシーケンスを理解すると、より明確になります。ここで理解しておくべきことは、大きな計算を小さな計算の合計に分解し続け、基本ケース(ifステートメント)に到達したときに停止することです。これで、すべての小さな計算を実行し、それらの小さな計算の結果を組み合わせて、最終的な答えが得られるまで、より大きな、より大きな結果を形成することができます。

再帰呼び出しがベースケースにヒットするたびに、ヒットしたケースに応じて1または0が返されます。この値は前の呼び出し元に返されます。理解するには、以下を考慮してください。

f(1)3 + f(0)3

ここで、添え字は再帰呼び出しツリーの深さを表すことに注意してください。呼び出しはf(2)2によって行われます。 f(1)3が最初に計算され、_1_がf(2)2に返されます。次にf(0)3が計算され、_0_がf(2)2に返されます。 2つの戻り値が合計され、結果は_1_になります。

f(2)2 thenreturns_1_を呼び出した人にit、これはたまたまf(3)1です。 f(3)1f(2)2 + f(1)2と呼ばれますが、この他のf(1)2も_1_をf(3)1に返します。これにより、f(2)2、_2_を形成します。

f(3)1は_2_をその呼び出し元であるf(4)0に渡します。これはたまたまf(3)1 + f(2)1 ...を呼び出したので、そのままです。


これを見る別の方法は、実際に行われた最初の関数呼び出しから開始することです:f(4)0

f(4)0f(3)1 + f(2)1を計算します。しかし、f(3)1を計算するには、f(2)2 + f(1)2を知る必要があり、同様に、f(2)1を計算するには、f(1)2 + f(0)2を知る必要があります。

36
cs95

いくつかの印刷ステートメントを追加すると、シーケンスを明確にするのにも役立ちます。

def f(n):
    print("Number received:", n)
    if n == 0:
        return 0
    if n == 1:
        return 1
    else:
        print("---- First recursion ----")
        a = f(n-1)
        print("---- Second recursion ----")
        b = f(n-2)
        print(" a=:",a,"; b=",b,"; returning:", a+b)
        return a + b

print("Final f(4)=", f(4))

出力:

Number received: 4
---- First recursion ----
Number received: 3
---- First recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
 a=: 1 ; b= 0 ; returning: 1
---- Second recursion ----
Number received: 1
 a=: 1 ; b= 1 ; returning: 2
---- Second recursion ----
Number received: 2
---- First recursion ----
Number received: 1
---- Second recursion ----
Number received: 0
 a=: 1 ; b= 0 ; returning: 1
 a=: 2 ; b= 1 ; returning: 3
Final f(4)= 3
3
rnso