我是Java新手,以下代码计算a ^ b,我已经在计算机上对其进行了编译,并且可以正常工作。但是我不明白它是如何工作的? Java编译器如何计算a * power(a, b - 1)
,有人可以向我解释这段代码吗?
int power(int a, int b) {
if (b < 0) {
return 0;
} else if (b == 0) {
return 1;
} else {
return a * power(a, b - 1);
}
}
答案 0 :(得分:8)
您的函数是递归的。用一个示例演示它的工作方式可能是最简单的。
假设您要计算2 ^ 4。
因此,您致电power(2, 4);
这是评估方式(请注意,您弄错了基本情况):
power(2, 4) // b > 0, so it expands.
2 * power(2, 3)
2 * (2 * power(2, 2))
2 * (2 * (2 * power(2, 1)))
2 * (2 * (2 * (2 * power(2, 0)))) // Now, b == 0, so it evaluates to -1
2 * (2 * (2 * (2 * -1)))
2 * (2 * (2 * -2))
2 * (2 * -4)
2 * -8
-16
答案 1 :(得分:1)
上述代码给出了错误的答案;第5行应显示为return 1;
,而不是return -1;
。
Java通过调用来计算对power
方法的调用。这里没有什么不同,因为您从power方法中调用power方法,可能会使您感到困惑。在Java中哪个还可以。
因此,让我们以power(3, 4)
为例。
Java将首先检查4是否小于0。不是,请跳过该操作。然后,如果它是0。则不是,所以跳过它。然后,它将返回表达式的结果(填写变量值):return 3 * power(3, 4 - 1)
。要计算该值,必须首先评估power(3, 3)
。
所以java ...做到了。它记得它在power(3, 4)
上做的一半(它在栈上完成),现在去计算power(3, 3)
。答案是评估return 3 * power(3, 2)
。因此,java记住power(3, 3)
完成的工作的一半,然后进行计算。答案是return 3 * power(3,1)
的结果。您猜对了,记住我们的工作并再次调用电源:return 3 * power(3, 0)
,但最后我们退出了:方法调用power(3, 0)
由第二个'if'解析,因此发生return 1;
。 power(3, 0)
成功完成!现在power(3, 1)
可以完成,然后power(3, 2)
可以完全完成,并返回81。
答案 2 :(得分:1)
这是递归。那是一个程序调用自己的时候。如果按所示放置打印语句,则可以看到它的工作原理。
static int power(int a, int b) {
if (b < 0) {
return 0;
}
else if (b == 0) {
return 1;
}
else {
System.out.println("Before: a = " + a + ", b = " + b);
int res = a * power(a, b - 1);
System.out.println(
"After: res = " + res + ", a = " + a + ", b = " + b);
return res;
}
}
每次更改值时,如对电源的调用所示,将b减小1。然后,当b == 0
时,程序开始返回,"retrieving"
来自调用堆栈的每个值都要做计算。
答案 3 :(得分:1)
它称为递归函数,该函数可自行调用。为确保它不会无限调用自身(并导致堆栈溢出;),请确保至少有一个退出条件。
退出条件是不调用函数本身的返回。
以以下示例为例:3^4
。实际上,3^4
与(3*3)*(4-1)
或(3*3*3)*(4-2)
或(3*3*3*3)*(4-3)
相同。这正是您对递归所做的!
在您的情况下,重新调用是
return a * power(a, b - 1);
(与我上面显示的完全一样)
您有2个退出条件:
if (b < 0) {
return 0;
} else if (b == 0) {
return -1;
}
答案 4 :(得分:0)
此代码适用于递归。每个递归调用都会推入一个新的堆栈框架,然后在返回时将其弹出。
您需要检查以上代码中的基本情况。因此,当b == 0时,它应该返回1。