なぜ、再帰メソッド内の「p n」をコメントアウトすると結果が正常になるのか?

このQ&Aのポイント
  • 再帰メソッド内の「p n」をコメントアウトすると、再帰が正常に終了するため、最後の「p myfact.fact(3)」の結果が3になります。
  • 再帰の構造では、最後に再帰メソッドが呼ばれる際に、その結果を返しつつ逆順に戻っていきます。
  • 「fact(3)」の実行では、3 * fact(2)となり、再帰処理が続きます。
回答を見る
  • ベストアンサー

再帰に関する質問です。

再帰に関する質問です。 class Test  def fact(n)    return 1 if n == 0    n * fact(n - 1)    p n  end end myfact = Test.new p myfact.fact(3) なぜ、"p n"をメソッドの中に入れると最後の "p myfact.fact(3)"の結果が3に なるのでしょうか。 "p n"をコメントアウトすると正常に6という結果がでます。 この再帰の構造は、 #1st loop fact(3)。 n = 3  3 * fact(2) end #2nd loop fact(2)  n = 2  2 * fact(1) end #3rd loop fact(1)  n = 1  1 * fact(0) end #last loop fact(0) return 1 end となってますよね。ここで最後のfact(0)から、リバースしていくわけで、 fact(1) 1 * 1 p n =>1 end fact(2) 2 * 1 p n => 2 end fact(3) 3 * 2 p n => 3 end ここまではわかります。ではなぜ最後の"p myfact.fact(3)"が3になるのでしょ うか。

  • Ruby
  • 回答数2
  • ありがとう数10

質問者が選んだベストアンサー

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

#1の方の指摘通りです。 def fact(n) return 1 if n == 0 n * fact(n - 1) p n end でn=3の場合のfactの戻り値は 明示的にreturn文で戻り値を指定していないため、 p nの評価結果になります。p n の評価結果は3なので戻り値は3になります。 factの内容を以下のように変えてください。 あなたの望んだ結果が得られるでしょう。 def fact(n) return 1 if n == 0 seki = n * fact(n - 1) p n return seki end

tukutukuhosi
質問者

お礼

ありがとうございます。理解できました。

その他の回答 (1)

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

ruby は return でメソッドを抜けなかった場合メソッド内で最後に評価した値をそのメソッドの戻り値とします。 http://docs.ruby-lang.org/ja/2.1.0/doc/spec=2fdef.html#eval_method また、 p も値を返します。 http://docs.ruby-lang.org/ja/2.1.0/class/Kernel.html#M_P 以上のことを踏まえてあなたの再帰関数をもう一度見直してみましょう。

tukutukuhosi
質問者

お礼

ありがとうございます。理解できました。

関連するQ&A

  • 再帰

    他の質問と平行してしまい申し訳ありません。再帰について少々おききしたいのですが、 配列の中にある数字の中から最大値と最小値を再帰処理でもとめたいのですが、うまくいきません。 public int minMax(n, array, min, max){ // nは配列のサイズです。 min=max=array[n-1]; if(array[n-2]<min) min=array[n-2]; if(array[n-2]>max) max=array[n-2]; return minMax(n-1,array,min,max); } 最初に比較するために min=max=array[n-1];と初期化したのですが、再帰処理ですからまた同じ初期化をしてしまうことになります。 forループなどを使えるなら初期化だけループの外でやれば済むのですが、再帰だとどのようにすればよいのでしょうか。 宜しくお願いいたします。

  • 関数の再帰処理

    1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657... という数列(フィボナ数列)を再帰処理でだしたいのですが・・・・・ include <stdio.h> int function( int ); int main( void ){ int n; do { printf( "0 以上の整数値を入力して下さい→ " ); scanf( "%d", &n ); }while ( n < 0 ); printf( "計算結果: %d\n", function( n ) ); getchar(); getchar(); return 0; } int function( int n ){ //フィボナの処理(function)の再帰呼び出しによる } function内に再帰処理を用いてprintf( "計算結果: %d\n", function( n ) );で画面出力したいのですが・・・・・・。

  • python ver3について

    python3を勉強している初心者です。 参考書に載っていた、階乗を計算する例題を変更したいと思っています。 このプログラムを書き換えて、input文で任意の数字nをキーボードから入力して、結果を表示させたいんですが、どうすれば良いでしょうか。 このプログラムでは思う様に動きません。 n=input() def fact(n):   if n ==0:     return 1   return n*fact(n-1) print(fact(n)) input() よろしくお願いいたします。

  • 再帰関数について

    非負の整数nに対して次のように定義された 関数F(n),G(n)がある。F(5)の値はいくらか。 関数 F(n):if n=<1 then return1 else return n×G(n-1) G(n):if n=0 then return0 else return n+F(n-1) (1)50 (2)65 (3)100 (4)120 正解 (2)65 以下解説 F(5):5×G(5-1)=5×(G(4))    =5×(4+F(4-1))=5×(4+(F(3)))    =5×(4+(3×G(3-1)))=5×(4+(+3×G(2))))    =5×(4+(3×(2+F(2-1))))=5×(4+(+3×(2+F(1)))))    =5×(4+(3×(2+(1))))    =65 再帰関数についての知識が皆無なので 教えて頂きたいのですが、なぜ=後の5×は残るのでしょうか。 そもそも再帰関数とは、どんなことを言っているのでしょうか。 具体例を挙げて頂くか、分かり易いURLを教えて頂けると幸いです。 お手数ですが、上記について1つ1つ丁寧に解説して頂きたいです。 大変ご迷惑な質問かと思いますが、分かる方おられましたら、 お手数ですが、ご教授お願いします。 以上、よろしくお願い致します。

  • Python 再帰関数関連

    再帰関数を解決できなくて困っています、ご教授お願いします! 普通関数で書いたものを再帰関数に変換するのはどう書けばいいですか? def foo(n, m):  sum = 0 while m > 0: sum = sum + n m = m -1 return sum これを再帰関数でどう変換します?

  • 再帰について(C言語)

    今、再帰処理を勉強しています。 しかし、以下のプログラムがどうしても理解できません。 流れ的には一体どういう手順になっているのでしょうか? return i * fact( i - 1 )の部分を考えると頭が こんがらがってしまいます。 #include <stdio.h> int main( void ){  printf("5の階乗は %d です", fact(5) );  return 0; } int fact( int i ){  if( i == 1 ) return 1;  else return i * fact( i - 1 ); } --------実行結果---------- 5の階乗は 120 です

  • c言語の再帰で(関数呼び出し)+1がわからない

    再帰がどのように処理されているのか理解するために、再帰の時に +1 してみたところ 0! = 1 1! = 2 2! = 5 3! = 16 4! = 65 5! = 326 6! = 1957 7! = 13700 8! = 109601 9! = 986410 10! = 9864101 となりました。 普通の階乗の値を求めた最後に +1され、それが戻されると思ったのですが違いました。 これはどういう処理がされているのでしょうか? #include <stdio.h> int kaijo(int); int main() { int i; for (i = 0; i < 11; i++) printf("%d! = %d\n", i, kaijo(i)); return 0; } int kaijo(int n) { if (n == 0) return 1; else return n * kaijo(n - 1) + 1; }

  • 再帰・組み合わせ

    新しく再帰という概念を習い始めたのですが、組み合わせを求めるやり方がわかりません 組み合わせの公式通り(nCk → n!/k!(n-k)!)、例えば4C2なら答えは6通りになるのはわかるのですが、 public static int combinations(int n, int k){ if(k==n){ return 1; }else if(k=1){ return n; }else if(0<k && k<n){ combinations(n-1, k-1) + combinations(n-1, k) ←これで出来るらしいのです } } combinations(n-1, k-1)は意味がわかるのですが、combinations(n-1, k)これが組み合わせの公式にどうあてはまっているのかがわからず、 そして何故足してるのかがよくわかりません。どなたかお解かりになればお願いします

    • ベストアンサー
    • Java
  • 再帰メソッドについて

    いつもお世話になっております。 再帰メソッドについて質問があります。 後述のプログラム実行後、以下の結果が 得られました。 ********** depth = [0] , value = [0] ********** depth = [1] , value = [1] ********** depth = [2] , value = [2] ########## depth = [2] , value = [3] …★ ########## depth = [1] , value = [3] recursionMethod() は3回呼ばれました。 (以下、ソース) public class RecursionTest { private static final int MAX_DEPTH = 2; private static int cnt = 0; private int val =0; public static void main(String[] args) { // 再帰メソッドの呼び出し RecursionTest own = new RecursionTest(); own.recursionMethod(0); System.out.println("\n recursionMethod() は" + cnt + "回呼ばれました。"); } private void recursionMethod(int depth) { // 再帰メソッドが呼ばれた回数をカウントする cnt++; System.out.println("********** depth = [" + depth + "] , value = [" + val + "]"); val++; // パラメータ depth が MAX値に到達したら、return する if (depth++ >= MAX_DEPTH) { return; } // 自分自身の呼び出し recursionMethod(depth); System.out.println("########## depth = [" + depth + "] , value = [" + val + "]"); } } 実行結果の★以降が得られる理由が全く分かりません。 ・return で main() に戻るはずなのになぜ「###~」のログが出力されるのか ・depth の値がなぜデクリメントされるのか (誰がデクリメントの処理をしているのか) そもそも上記の結果を返すことが「メソッドの再帰的呼び出し」ということなのでしょうか? ご教授頂ける方がいらっしゃいましたら、宜しくお願い致します。

    • ベストアンサー
    • Java
  • 再帰呼び出しの計算量

    再帰呼び出しを用いた関数の計算量を求める方法がわからないので質問させていただきます. xのn乗を再帰呼び出しを用いて求める関数に関して,計算量を求める問題なのですが,どのような方針で求めればよいのでしょうか? int exponent(int x, int n) {   if(n == 0){     return 1;   }else{     return x * exponent(x, n-1);   } } exponentがn回呼ばれるからO(n)というのは間違いでしょうか?

専門家に質問してみよう