javascript中的递归和返回

时间:2012-03-06 07:57:40

标签: javascript recursion

我正在CodeAcademy.com学习Javascript,我很难理解一个练习题,虽然我似乎找到了正确的答案。

该代码旨在帮助某人计算出当有人购买时他们应该回馈多少变化。它需要一个数字,并计算他们应该回馈多少个季度和多少便士。

这是我不明白的地方:

•第一次遇到第11行时,代码是否应该停止运行?如果没有,为什么不呢?

•如果代码在进入第11行时确实停止运行,为什么我能够在第10行之后放置代码并且它会在给出答案之前执行三次?我发现情况就是这样,所以它让我质疑我对代码如何工作的理解!我在第10行之后添加了行quarters += 1;,它返回6。

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");

7 个答案:

答案 0 :(得分:3)

代码在第11行上没有第一次停止运行,因为它第一次到达第10行时(有效地)返回到第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;

答案 1 :(得分:1)

不一定。使用递归,您可能会多次调用函数,并且每次调用都需要在代码完成函数执行之前返回。因此,如果howManyQuarters被调用3次,它将在函数调用之后立即执行代码(在这种情况下是返回语句),这也是很多次。

希望这很清楚。

答案 2 :(得分:1)

这是递归的全部要点:函数调用自身直到满足停止条件并变为true,然后它将不再调用自身。

在这种情况下,是的,函数确实会停在return quarters;行,但此时它已经在行中调用了自己。

停止条件是确保你没有无限循环 - 当调用函数时,你给它一个数字 - 当这个数字小于0.25时,函数将停止。所以:

基本示例:

  1. 如果初始数小于0.25,则该函数仅运行一次,返回0.
  2. 如果初始数字介于0.25和0.5之间,则函数将运行两次 - 自调用(递归)将发生一次,因为该值不小于0.25但自调用传递值减去0.25 所以现在第二次调用的值已经小于0.25 - 满足停止条件,一切都很好。
  3. 返回值本身由在函数外部声明的全局变量管理 - 每次函数调用自身时,它会将该变量递增1,因此最后您知道它被调用了多少次。现在你可以在this example中看到它并不是很聪明 - 第二次调用具有相同变化量的函数会带来错误的结果。

答案 3 :(得分: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匹配,函数可以在不调用自身的情况下进行计算。否则,它会调用自己传递较小的数据集。递归函数的计算过程可以通过堆栈表示:每次调用函数时我都会进入堆栈,当函数返回一个值时,我会弹出堆栈。第一个pop将始终是baseCondition块的结果。

警告:如果baseCondition永远不匹配,最终将发生堆栈溢出。

一个典型的例子是整数的阶乘函数:

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

有关详细信息,请参阅here

答案 4 :(得分:0)

每次输入该功能时,最终都必须通过return退出。这是一个图表:

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

答案 5 :(得分:0)

对不起,有点offtopic,但为什么你需要这么简单的数学工作这么复杂的功能?这实际上是一行函数需要(但是汇总结果)。

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

就是这么简单。

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

答案 6 :(得分:0)

这里我能想到的是

return quarters;
在第10行之后没有执行

语句。 当控件遇到

howManyQuarters(howMuchMoney-0.25);

语句它自己调用而不执行第11行。 完成所有递归后,控件从每个循环(递归)中出来并执行第11行。