重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

こんばんは
再帰についておしえてください。
実行結果は120となります。
F8で動作を追っていくと
Sample_subに5を渡してn<=1になるとENDIFにうつり
その後、END funtionとEndifの間をいききしております。
どうして、こういう動作をするのでしょうか?
よろしくおねがいいたします。

Sub sample()
MsgBox sample_sub(5)
End Sub
Function sample_sub(ByVal n As Integer)
If n <= 1 Then
sample_sub = 1 'ここで再帰処理は終了します。
Else
sample_sub = n * sample_sub(n - 1) 'ここで自分自身を呼び出しています。
End If
End Function

質問者からの補足コメント

  • こんばんは
    ご回答ありがとうございます。
    すみません。基本的なことでもうしわけございません。
    Function sample_sub(ByVal n As Integer)
    If n <= 1 Then
    sample_sub = 1
    Else
    sample_sub = n * sample_sub2(n - 1)
    End If
    End Function
    -------------
    のとき、 どしてsample_sub2(n - 1)なのでしょうか?
    よろしくお願いいたします。

    No.1の回答に寄せられた補足コメントです。 補足日時:2017/03/06 17:49
  • つらい・・・

    丁寧な説明ありがとうございます。
    なんとなくわかりました。わかったつもりかもしれません。すみません。
    計算の流れとして、(先ほどのご回答いただいた流れから)
    sample_sub_5を求める場合、=5 * sample_sub_4()なのでsample_sub_4()
    が呼び出され、sample_sub_4 = 4 * sample_sub_3()なので、 sample_sub_3()に
    さらにお伺いを立て・・・N=1のときは sample_sub_1 = 1なので、そこを起点に計算され、結果sample_SUB_5がもとめられ、sample_SUBへ渡されるということでしょうか?
    もしくは、end if endfunctionを行き来していた時、ウォッチりすとでみたら、N=1から順に5までへんかしていたので全然違う方法で処理がおこなわれているのでしょうか?
    宜しくお願いいたします。

    No.5の回答に寄せられた補足コメントです。 補足日時:2017/03/09 12:21

A 回答 (5件)

VBA の


Function名 = 戻り値
って書き方に惑わされていませんか?
> sample_sub(5)
で呼び出したときの sample_sub=〜 と、その中の
> sample_sub = n * sample_sub(n - 1) 'ここで自分自身を呼び出しています。
にある sample_sub(n - 1) で呼び出されたときの sample_sub=〜 とは、別なものになります。
「一つの変数sample_sub」 の値が変化しているわけではありません。
ステップ実行で見ると、プログラムの同じ行を指しているので「一つの変数sample_sub」 の値が変化している」様に見えてしまいますが、そうではないのです。


別の例を用意します。
sample_sub(5) で呼び出したのと、同じ動きをする関数 sample_sub_5 を作ります。

Function sample_sub_5()
If 5 <= 1 Then
sample_sub_5 = 1
Else
sample_sub_5 = 5 * sample_sub_4()
End If
End Function

同様に4〜1を用意します

Function sample_sub_4()
If 4 <= 1 Then
sample_sub_4 = 1
Else
sample_sub_4 = 4 * sample_sub_3()
End If
End Function

Function sample_sub_3()
If 3 <= 1 Then
sample_sub_3 = 1
Else
sample_sub_3 = 3 * sample_sub_2()
End If
End Function

Function sample_sub_2()
If 2 <= 1 Then
sample_sub_2 = 1
Else
sample_sub_2 = 2 * sample_sub_1()
End If
End Function

Function sample_sub_1()
If 1 <= 1 Then
sample_sub_1 = 1
Else
sample_sub_1 = 1 * sample_sub_0()
End If
End Function


この sample_sub_5() での動作は、 sample_sub(5) とまったく同じになります。
この回答への補足あり
    • good
    • 0
この回答へのお礼

いろいろとありがとうございました。
ご説明いただき徐々にわかっていったような気がします。
ご参考に 再帰のページをみつけました。
http://www.koikikukan.com/archives/2014/12/12-00 … 
よろしければ見てください。
一番したのほうに120になる処理順序がかかれておりました。
確かにこのように動作してました。
長いあいだお付き合いいただきまして大変感謝しております。
本当にありがとうございました。

お礼日時:2017/03/14 15:34

Function sample_sub2(ByVal n As Integer)


If n <= 1 Then
sample_sub2 = 1
Else
sample_sub2 = n * sample_sub3(n - 1)
End If
End Function
と書きました。
元のsample_subと(ほぼ)同じ内容ですから、結果も同じになります。

つまり
sample_sub(n - 1)
と書いても
sample_sub2(n - 1)
と書いても
結果は同じです。



再帰呼出がわからなくなる人は、「関数の先頭に戻る」と考えてしまうことが多いように思います。

> Sample_subに5を渡してn<=1になるとENDIFにうつり
> その後、END funtionとEndifの間をいききしております。
と考えてしまうのは、
> sample_sub = n * sample_sub(n - 1) 'ここで自分自身を呼び出しています。
で「関数の先頭に戻る」と考えてしまっていて、
End Functionまでいったら、呼び出し側の「MsgBox sample_sub(5)」に戻るのが「正しい」と考えてしまっているのでは?
    • good
    • 0
この回答へのお礼

ありがとうございます。 n=5のとき、sample_sub4 n=4のとき、sample_sub3
n=3のとき sample_sub2 n=2のとき sample_sub1
①この段階で、sample_subはemptyと表示されてます。
その後、If n <= 1 Then  sample_sub2 = 1
IFが終わり、その後、n=1のときsample_sub 1 
N=2のとき sample_sub 2 n=3のとき sample_sub 6
n=4のときsample_sub  24 N=5のときsample_sub 120 
ーーーーーーーーーーー
①の段階でsample_sub1から4はそれぞれの領域のメモリにう格納され、IF文がおわったら、蓄積されたものをつかって、N=1から計算をしているのでしょうか?また、そのときどして値がN=1からN=5に順にふえるのでしょうか?②前回 実行結果が120と表示されていたので120と記載したのですが・・・sample_sub2 = n * sample_sub3(n - 1)のときに たとえば、N=3のきにsample_subが6になるのでしょうか?(このとき、sample_sub2 =3*sample_sub3(n-1)どのようにして6とみちびきだせるのでしょうか?)よろしくお願いいたします。

お礼日時:2017/03/07 00:25

行きと帰りでいいんじゃないでしょうか?


呼び出しまでを行き、その後を帰りとして
行きを5回みたら、帰りも5回ありますよね。
    • good
    • 0

私は、このように考えました。


If ~ End If 構文がネストになっていると同じことではないでしょうか。
ネストは、If の中にIf があって・・・・と続くから、当然、End If も処理しないと終われないと同じようなことではないかと思います。
    • good
    • 0

再帰関数は、「別の関数を呼んでいる」と考えると、理解の助けになると思います。


例えば

Function sample_sub(ByVal n As Integer)
If n <= 1 Then
sample_sub = 1
Else
sample_sub = n * sample_sub2(n - 1)
End If
End Function

Function sample_sub2(ByVal n As Integer)
If n <= 1 Then
sample_sub2 = 1
Else
sample_sub2 = n * sample_sub3(n - 1)
End If
End Function

というように。
さて、このとき、 動きを考えると
sample_sub:
sample_sub = n * sample_sub2(n - 1)

 sample_sub2: sample_sub2 = n * sample_sub3(n - 1)
 →
 ... sample_sub3: End Functionで 戻ってくる
 sample_sub2: End If
 sample_sub2: End Functionで 戻ってくる
sample_sub: End If
sample_sub: End Functionで 戻ってくる

これはわかりますね?

これが、実際は sample_sub という一つの関数を再帰呼び出ししたものなので、見た目では 「endifとend functionを繰り返している」ように見えています。
この回答への補足あり
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!