簡體   English   中英

遞歸冪 function:如果沒有初始返回值,為什么會這樣?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM