2012-03-06 33 views
1

私はCodeAcademy.comでJavascriptを学習していますが、私は正しい答えを見つけたようですが、運動の質問を理解するのが難しいです。JavaScriptの再帰と戻り

コードは、誰かが何かを購入したときにどれだけの変更を返すべきかを理解するのに役立つように設計されています。それは数を取り、返すべき四分の一とペニーの数を計算します。

を•コードストップが、それはライン11に遭遇した最初の時間を実行していない必要があります。ここでは

は、私は理解していない何ですか?そうでない場合は、どうしてですか?

•11行目に入ったときにコードの実行が停止すると、10行目以降にコードを置くことができます。なぜなら、答えが出る前に3回実行されるからです。私はこれが事実であることを発見したので、コードがどのように機能していたかについて私の理解に疑問を呈しました!私は、10行目の後に行quarters += 1;を追加し、それは必ずしもそうではありません

var change = 0; 
var quarters = 0; 
function howManyQuarters(howMuchMoney) { 
    if (howMuchMoney < 0.25) { 
    change = howMuchMoney; 
    return 0; 
    } 
    else { 
    quarters += 1; 
    howManyQuarters(howMuchMoney-0.25); 
    return quarters; // << line 11 
    } 
} 

change = 0.99; 
console.log ("Pay out " + howManyQuarters(change) + " quarters"); 
console.log ("And you'll have " + change * 100 + " pennies left over"); 
+0

howManyQuarte howManyQuerters(.99-.25) - > howManyQuarters(.74-.25)... 10行目では、関数は自身を呼び出しますが、値は小さくなります。これは、4行目の条件が真になるまで繰り返され、すべてがスタックに戻ります。 1つのエクササイズは、あなたがリターン0になるまでスタック全体をトレースし、それからそれをトレースすることです。 – jmort253

+0

コードは11行目で停止し、関数howManyQuartersが値 –

+0

を返します。私が理解していないこと:もし10行目と11行目の間に再度四分の一+ = 1を加えれば、それは6の答えを与えるでしょう。なぜそれが別の3四半期を追加するのだろうか?私はそれがもう1つだけ追加すると思った? – inperspective

答えて

1

6を返します。再帰では、潜在的に関数を複数回呼び出すことになり、関数のコードの実行が完了する前に各呼び出しを返す必要があります。したがって、howManyQuartersが3回呼び出されると、関数コール(この場合はreturn文)の直後のコードが何度も実行されます。

希望は明らかです。

+0

あなたの答えをありがとう。それは役に立ちます。これに関する詳細情報を検索するために、どのような用語を検索できますか? – inperspective

1

これは、再帰の全体点です。関数は、ストップ条件が満たされてtrueになるまで自身を呼び出していて、それ以降はそれ自身を呼び出しません。

この場合、関数は実際にはreturn quarters;行で停止しますが、この時点ではすでにその行の前に既に呼び出されています。

ストップコンディションでは、無限ループが発生しないようにしています。関数を呼び出すときに数値を指定します。その数値が0.25未満の場合、関数は停止します。だから、:

基本例:

  1. 場合は、最初の数だった初期の数は0.25と0.5倍に実行する関数の間であった場合は0
  2. を返す関数は一度だけ実行されます0.25未満 - 値が0.25より小さくないので自己呼び出し(recursion)が1回起こりますが、自己呼び出しは値から0.25を引いた値になります。したがって、2番目の呼び出しの値はすでに0.25未満になります。良い。

戻り値自体は、関数の外部で宣言されたグローバル変数によって管理されます。関数自体が呼び出されるたびに、その変数が1だけインクリメントされるため、呼び出された回数がわかります。 this exampleに表示されているようにそれほどスマートではありません - 同じ量の変更を伴う関数への2番目の呼び出しは間違った結果をもたらします。それは(事実上)ライン10に到達した最初の時間ので

3

コードは、ライン11上の最初の時間の実行を停止しないことをこのように想像してみてください3

行目に戻ります。私は再帰のレベルをラインアップしました:

1. (Line 15) howManyQuarters(0.99) 
    2. (Line 4) howMuchMoney is > 0.25...so else applies 
    3. (Line 10) howManyQuarters(0.74) --> 0.74 = 0.99-0.25 
     4. (Line 4) howMuchMoney is > 0.25...so else applies 
     5. (Line 10) howManyQuarters(0.49) --> 0.49 = 0.74-0.25 
      6. (Line 4) howMuchMoney is > 0.25...so else applies 
      7. (Line 10) howManyQuarters(0.24) --> 0.24 = 0.49-0.25 
       8. (Line 4) howMuchMoney is < 0.25...so enter main body of if clause 
       9. (Line 6) return 0; 
      11. (Line 11) return quarters; 
     12. (Line 11) return quarters; 
    13. (Line 11) return quarters; 
14. (Line 11) return quarters; 
+0

あなたの答えをありがとう。それは私がそれが働いたと想像している方法ですが、私が理解していないことがまだあります。10行目と11行目の間に再度四分の一+ 1を追加すると、6の答えが得られます。なぜそれが別の3四半期を追加するのだろうか?私はそれがもう1つだけ追加すると思った?これは、10行目のコードが3回も実行されていることを示しています。 – inperspective

+0

@RicardoCollinsこれは、呼び出された関数の実行後に、その関数呼び出しの次の式からプログラムフローが続行されるためです。 9行目と10行目を切り替えることもできますが、結果は同じになります。 – Teemu

+0

好奇心に満ちていない、 – inperspective

0

機能が入力されるたびに、それが最終的にreturnを経由して出ることがあります。ここでは図です:、

Enter howManyQuarters. 
    Enter howManyQuarters. 
    Enter howManyQuarters. 
     Enter howManyQuarters. 
     return 
    return 
    return 
return 
0

申し訳ありませんが、少しofftopicが、なぜあなたは、単純な数学の仕事のためにこのような複雑な機能が必要なのでしょうか?これは、実際には1行の関数が代わりに必要です(ただし、結果は集計されています)。

function howMuchMoney(val) { 
    return [ 
     Math.floor(val/0.25), 
     parseFloat((val % 0.25).toFixed(2)) 
    ]; 
} 

これはまったく簡単です。

http://jsfiddle.net/semencov/D8xUE/

1

機能が正しいです。再帰はコンピュータ科学の驚くほど強力な方法です。

function myRecursive(nSizeData){ 
    if(baseCondition is TRUE){ 
    //compute the function with nSizeData 
    //do stuff here 
    } 
    else{ 
    //call the same function with a smaller size set of data 
    //this condition ensure that the baseCondition will eventually be matched 
    myRecursive(mSizeData); 
    } 
} 

機能の基礎を表す基礎条件があります:関数入力データがbaseConditionと一致した場合、この関数は自分自身を呼び出すことなく計算することができます再帰関数は常に同じ構造を有しています。さもなければ、より小さなサイズのデータ​​セットを渡して自分自身を呼び出します。再帰関数の計算プロセスは、スタックを介して表現することができます。関数が呼び出されるたびにスタックにプッシュし、関数が値を返すとスタックをポップします。最初のポップは常にbaseConditionブロックの結果になります。

警告:baseConditionが決して一致しない場合、最終的にstackoverflowが発生します。

function factorial(n){ 
    if(n==0 || n==1){ 
    return 1; 
    } 
    else{ 
    return factorial(n-1); 
    } 
} 

は詳細についてhereを参照:

古典的な例では、整数の階乗関数です。私が考えることができるものをここで

+0

あなたの答えをありがとう。私はあなたの答えであなたが言うことを理解していると思うが、私が理解していないことはこれである:もし10 + 11の四分の一をもう一度加えると、6の答えが出る。なぜそれが別の3四半期を追加するのだろうか?私はそれがもう1つだけ追加すると思った? – inperspective

+0

これは再帰を助けました。 +1 – montecruiseto

0

return quarters; 

文がちょうどライン後に実行されていないということであるコントロールが、それは実行せずに自分自身を呼び出す

howManyQuarters(howMuchMoney-0.25); 

声明が発生した10 すべての再帰が行われると、制御は各ループ(再帰)から抜け出し、11行目を実行します。