[英]Recursive power function: Why does this work if there's no initial return value?
因為 power(base, exponent) 沒有返回值,除非 exponent 為 0,所以最初,power(base, exponent -1) 不應該返回“未定義”,因此最初是不可乘的嗎? 所以,我在遵循這段代碼的邏輯時遇到了麻煩。 為什么/它是如何工作的?
function power(base, exponent) {
if (exponent == 0)
return 1;
else
return base * power(base, exponent - 1);
}
看看如果您嘗試計算5^3
會發生什么:
power(5, 3) ... this should give us 125, let's see if it does...
function power(base, exponent) { // base = 5, exponent = 3
if (exponent == 0) // nope, exponent != 0
return 1;
else
return base * power(base, exponent - 1); // return 5 * power(5, 2)
}
... 什么是power(5, 2)
? ...
function power(base, exponent) { // base = 5, exponent = 2
if (exponent == 0) // nope, exponent != 0
return 1;
else
return base * power(base, exponent - 1); // return 5 * power(5, 1)
}
...什么是power(5, 1)
? ...
function power(base, exponent) { // base = 5, exponent = 1
if (exponent == 0) // nope, exponent != 0
return 1;
else
return base * power(base, exponent - 1); // return 5 * power(5, 0)
}
...什么是power(5, 0)
? ...
function power(base, exponent) { // base = 5, exponent = 0
if (exponent == 0) // yup, exponent != 0
return 1; // return 1
else
return base * power(base, exponent - 1);
}
...將它們放在一起,當我們走回堆棧時以相反的順序......
power(5, 0) = returns 1
power(5, 1) = 5 * power(5, 0) = 5 * 1 = returns 5
power(5, 2) = 5 * power(5, 1) = 5 * 5 = returns 25
power(5, 3) = 5 * power(5, 2) = 5 * 25 = returns 125
... so, power(5, 3) returns 125, as it should.
它可以更簡潔:
function power(base, exponent) {
return exponent == 0? 1 : base * power(base, --exponent);
}
然而,迭代解決方案要快得多:
function powerNR(base, exp) {
var result = 1;
while(exp--) {
result *= base;
}
return result;
}
我認為這個函數反過來更有意義,像這樣:
const power = (base, exponent) => {
if (exponent !== 0) {
return base * power(base, exponent - 1);
} else {
return 1;
}
}
if 語句的返回被鏈接在一起,並且在執行else 語句之前無法解析。
例子
4^0 = else;
4^0 = 1
4^1 = if * else;
4^1 = 4 * 1;
4^2 = if * if * else;
4^2 = 4 * 4 * 1;
= 4 * 4;
= 16
// Another way of conceptualising it:
4^2 = if(if(else));
= 4(4(1));
= 16;
請記住,它是if/else 語句的返回,被傳遞回鏈到調用它的函數。
一個略顯愚蠢的比喻
假設你想問大衛一個問題但你不想大喊大叫,你可以問你旁邊的人,誰可以問你旁邊的人,誰可以問你旁邊的人,等等,直到問題是問大衛。
const askDavidAQuestion = peopleInBetweenYouAndDavid => {
if (peopleInBetweenYouAndDavid !== 0) {
console.log('I will ask him');
return askDavidAQuestion(peopleInBetweenYouAndDavid - 1);
} else {
console.log('David says no');
}
}
askDavidAQuestion(3);
-> I will ask him
I will ask him
I will ask him
David says no
只有知道 David 的答案后,這條信息才能在提出問題的人鏈中傳回。
創建了對該函數的調用堆棧。 這個過程一直持續到它滿足終止條件/“基本情況”——這里是一個返回值。 此時,所有函數都可以返回並且原始函數調用返回答案。 換句話說,返回值從堆棧中彈出並用於計算下一步(以相反的順序),依此類推,直到堆棧為空。
使用2^2
示例:
power(2, 2);
調用:
function power(2, 2) {
if (2 === 0) {
return 1;
} else {
return 2 * power(2, 1); // Called (waits in line to be solved)
}
}
這將導致:
function power(2, 1) {
if (1 === 0) {
return 1;
} else {
return 2 * power(2, 0); // Called (waits in line to be solved)
}
}
這將導致:
function power(2, 0) {
if (0 === 0) {
return 1; // Returned (previous calls to recursive case can now be solved)
} else {
return 2 * power(2, -1);
}
}
現在它有一個返回值可以使用,它可以向外工作,可以這么說。
這將導致:
function power(2, 1) {
if (1 === 0) {
return 1;
} else {
return 2 * 1; // Returned
}
}
這將導致:
function power(2, 2) {
if (2 === 0) {
return 1;
} else {
return 2 * 2; // Returned
}
}
最終返回 4,即 2^2。
如果指數為負,所有列出的版本都將不起作用。 Math.pow()的正確實現版本應該這樣完成 -
function pow(num1, num2){
if (num2 === 0){
return 1;
}
else if(num2 < 0){
num2 = Math.abs(num2);
return (1 / pow(num1, num2));
}
else if(num2 > 0){
return num1 * (pow(num1,num2 - 1));
}
};
function pow(base, exponent) {
if (exponent === 0) return 1;
if (exponent > 0) {
return base * pow(base, exponent - 1)
} else {
// handle negative exponent
return 1 / base * pow(base, exponent + 1)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.