我正在尝试学习如何使用递归函数,但我不了解发生了什么。
function power(base, exponent) {
return base * power(base, exponent - 1);
};
alert(power(4,4));
我得到了:
RangeError:超出最大调用堆栈大小。
从我要离开的例子来看,它有:
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
alert(power(4,4));
有人可以向我解释为什么需要if语句吗?我怀疑我错过了什么。
答案 0 :(得分:8)
递归函数调用自身。这就是它的定义。
这带来了一个问题:它将无限期地调用自己。所以它将永远存在,这就是为什么你会得到堆栈溢出。
相反,你应该停在某一点上。这是if
子句的来源。当exponent == 0
时,您不调用该函数,而是停止该过程。
因此,在执行power(3, 3)
时,它会像:
power(3, 3) is equal to:
3 * power(3, 2)
or 3 * 3 * power(3, 1)
or 3 * 3 * 3 * power(3, 0)
or 3 * 3 * 3 * 1 // no additional calls anymore; can be calculated now
从一个不同的角度看:
power(4, 4)
被函数定义为4 * power(4, 3)
。power(4, 3)
被函数定义为4 * power(4, 2)
。power(4, 2)
被函数定义为4 * power(4, 1)
。power(4, 1)
被函数定义为4 * power(4, 0)
。power(4, 0)
被函数定义为1
。如果您将所有内容替换为前一个内容,您将获得:
power(4, 4)
equals 4 * power(4, 3)
equals 4 * 4 * power(4, 2)
equals 4 * 4 * 4 * power(4, 1)
equals 4 * 4 * 4 * 4 * power(4, 0)
equals 4 * 4 * 4 * 4 * 1
equals 256
答案 1 :(得分:5)
在递归中需要一个基本案例,以便它停止调用自身。在这种情况下,幂函数被永远调用(好吧,直到javascript解释器放弃),因为指数变为负无穷大。
答案 2 :(得分:3)
递归函数调用自身。因此,您需要一些机制来告诉它停止,否则您将处于无限循环中。在你的情况下,你总是返回并且没有提供退出循环的方法。因此RangeError。
答案 3 :(得分:3)
请注意,该函数正在调用自身。在您的第一个示例中,函数调用自身,然后新调用的函数调用自身,依此类推。在内部,您的计算机将这些函数调用存储在称为堆栈的内存结构中。当没有更多用于存储函数调用的内存时,您已超出调用堆栈大小。
在第二个例子中,你有办法摆脱这种恶性循环。基本情况允许函数返回,因此您将方法调用“弹出”到堆栈中。
请注意,在第二个示例中,您可以从alert(power(4,-1))开始,然后您将再次遇到相同的问题,因为现在您的函数将从-1中减去1,给出-2,并且等等。您可以使用
强化代码if (exponent <= 0 )
......而不是。
答案 4 :(得分:2)
你必须给它一些角落条件,否则它会一遍又一遍地自我调用。由于堆栈大小有限,它将到达堆栈内存的末尾,然后将抛出错误。
答案 5 :(得分:2)
递归实际上是在它自己的函数体内再次调用函数&amp;再次,直到你得到你想要的结果。
public int FactorialOfNumber(int k) {
if (k==1)
return 1;
else
return k * FactorialOfNumber(k-1); //Function called within Function.
}
Recursion使用堆栈运行会发生什么?
假设k = 1,则返回1.
如果k = 4,则控制转到else,返回(4 * FactorialOfNumber(3))。因为你不知道,FactorialOfNumber(3)。它存储在堆栈顶部。
现在,k = 3,控制转到else,它返回(3 * FactorialOfNumber(2))。这就是堆栈顶部。
现在k = 2,返回(2 * FactorialOfNumber(1)),堆栈顶部。
最后它调用了来自堆栈的pop,最后调用了(4 * FactorialOfNumber(3))。
如果递归方法永远不会达到基本情况,那么堆栈永远不会停止增长。但是,计算机将堆栈限制在特定高度,因此没有程序会占用太多内存。如果程序的堆栈超过此大小,计算机将启动异常,这通常会使程序崩溃。该异常标记为StackOverflowError。
答案 6 :(得分:1)
当指数达到零时,if创建一个检查以停止递归。没有它,它将继续负值并永不停止。