JavaScript >> Javascript 文檔 >  >> JavaScript

使用 JavaScript 計算階乘 - 迭代和遞歸

簡介

數字的階乘 是該整數與所有小於或等於它的正整數的乘積。它必須是一個正整數 - 否則,邏輯擴展到負無窮大。換句話說 - 計算階乘意味著將一個數字與 1 之間的所有整數相乘。

階乘由我們計算階乘的整數表示,後跟一個感嘆號。

為了計算階乘,我們將這個數字乘以每個小於它的整數,直到我們達到 1:

5! = 5 * 4 * 3 * 2 * 1
5! = 120

在本教程中,我們將學習如何使用 JavaScript 計算整數的階乘,使用循環和遞歸。

使用循環計算階乘

我們可以使用 while 來計算階乘 循環和 for 環形。我們通常只需要一個用於循環終止的計數器和我們正在為其計算階乘的提供的數字。

讓我們從 for 開始 循環:

function getFactorialForLoop(n) {
    let result = 1;
    if (n > 1) {
        for (let i = 1; i <= n; i++) {
            result = result * i;
        }
        return result;
    }
    else {
        return "n has to be positive";
    }
}

您可能已經觀察到我們從 1 開始計數 ,而不是 n - 即使階乘的定義表明我們從 n1 .雖然,在數學上,這些是等價的陳述:

$$
1 * 2 * 3 * 4 ... * n =n * (n-1) * (n-2) * (n-3) * (n-4) ... * (n - (n-1))
$$

這意味著我們計算的方向無關緊要。它可以從 1 開始 向 n 方向增加 , 也可以從 n 開始 向1遞減 .說清楚了,我們來看看這個方法到底發生了什麼。

它接受 n ,我們正在計算階乘的數字。 1 的值 分配給佔位符 result 變量,最終會被更新。

如果我們分配 0 對它 - 以下所有乘法都將使用 0 .這最終只有一個 0 最後。

然後我們開始我們的for 循環定義 i 作為從 1 開始的計數器 .注意條件語句是i <= n; 為了包含 n 自己也是。

for 內部 循環,我們乘以 result 的當前值 使用我們索引 i 的當前值 - 執行定義中的操作反向 .

最後,我們返回result的最終值 作為方法的輸出。讓我們在瀏覽器的控制台中測試我們的功能並打印出結果。一定要先在瀏覽器的控制台輸入階乘函數:

var inp = window.prompt("Enter a number: ");
inp = parseInt(inp);

alert("The result is: " + getFactorialForLoop(inp));

它將提示用戶輸入。我們將嘗試使用 4 .當您運行警報腳本時,您會看到一個帶有結果的彈出窗口:

24

您可以使用計算器來驗證結果:

4!4 * 3 * 2 * 1 , 結果 24 .

現在讓我們看看如何使用 while 計算階乘 環形。這是我們修改後的函數:

function getFactorialWhileLoop(n){
    let result = 1;
    while (n > 1) {
        result = result * n;
        n -= 1;
    }
    return result;
}

這與 for 非常相似 環形。除了這次我們從 n 朝向1 - 更接近數學定義。讓我們測試一下我們的功能:

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

var inp = window.prompt("Enter a number: ");
inp = parseInt(inp);

alert("The result is: " + getFactorialWhileLoop(inp));

和之前一樣,如果我們輸入 4 我們得到 24 .計算結果為 4*3*2*1 最後的結果和之前一樣。

階乘是遞歸的 在本質上,使用遞歸是一種更自然的方法來重複多次這樣的操作。

使用遞歸計算階乘

遞歸函數是調用自身的函數 .一開始可能聽起來有點嚇人,但請耐心等待,您會發現遞歸函數很容易理解。

一般來說,每個遞歸函數都有兩個主要部分:基本情況 和一個遞歸步驟 .

基本情況 是問題的最小實例 - 這就是重複。也是一個休息,一個將返回一個值並將退出的案例 的遞歸。就階乘函數而言,基本情況是我們返回階乘的最後一個元素,即 1 .

遞歸步驟——顧名思義——是函數的遞歸部分,其中整個問題被轉化為更小的問題。如果遞歸步驟未能縮小問題,那麼再次遞歸可以無限運行。

考慮階乘的重複部分:

  • 5!5 * 4 * 3 * 2 * 1 .

但我們也知道:

  • 4 * 3 * 2 * 1 4! .

換句話說 5!5 * 4! , 和 4!4 * 3! 等等。

階乘遞歸在到達 1 時結束 .這將是我們的基本情況 .我們將返回 1 如果 n1 或更少,覆蓋零輸入。

讓我們看看我們的遞歸階乘函數:

function getFactorialRecursively(n){
    if (n <= 1){
        return 1;
    }
    else{
        return n * getFactorialRecursively(n-1);
    }
}

如您所見,if 塊體現了我們的基本案例 , 而 else 塊覆蓋遞歸步驟 .

讓我們測試一下我們的功能:

var inp = window.prompt("Enter a number: ");
inp = parseInt(inp);

alert("The result is: " + getFactorialRecursively(inp));

我們將輸入3 這次作為輸入,警報將打印 6 結果。

我們得到相同的結果。但這一次,引擎蓋下的內容相當有趣:

你看,當我們輸入輸入時,函數會檢查 if 塊,由於 3 大於 1,它會跳到 else 堵塞。在這個塊中,我們看到 return n * getFactorialRecursively(n-1); 行 .

然後程序再次調用相同的函數,但是 這次我們的函數需要 2 作為參數。它檢查 if 阻止並跳到 else 塊並再次遇到最後一行。現在,n 的當前值 是 2 但程序仍然必須計算 getFactorialRecursively(n-1) .

所以它再次調用該函數,但這次是 if 塊,或者更確切地說,基類成功返回 1 並從遞歸中中斷。

按照相同的模式向上,它返回每個函數結果,將當前結果與之前的 n 相乘 並為上一個函數調用返回它。換句話說,我們的程序首先到達階乘的底部(即 1),然後逐步向上構建,同時在每一步中相乘。

也將函數從調用棧中一一移除,直到n * (n-1)的最終結果 被退回。

這通常是遞歸函數的工作方式。一些更複雜的問題可能需要使用不止一個基本案例或不止一個遞歸步驟進行更深層次的遞歸。但是現在,這個簡單的遞歸已經足夠解決我們的階乘問題了!

結論

在本文中,我們介紹瞭如何使用 for 計算階乘 和 while 循環。我們還學習了遞歸是什麼,以及如何使用遞歸計算階乘。

如果您喜歡遞歸併想練習更多,請嘗試使用遞歸計算斐波那契數列!如果您對我們的文章有任何疑問或想法,請隨時在評論部分分享。


Tutorial JavaScript 教程
  1. Webkit-Transform:Scale 在 HTML5 全屏模式下不起作用(僅限 Chrome)

  2. 使用 SVG + JS 構建平滑的動畫 blob

  3. Reacts JS:有狀態與無狀態組件

  4. SolidJS - React 遇到 Svelte?

  5. 使用 Redux 和 TypeScript 簡化 Connected Props

  6. 使用 Simplr 路由器

  7. ng-class 中的表達式

  1. 帶有 VueJS 的 Toast 或警報框組件

  2. 我們如何決定升級我們的 JavaScript 課程以使用 React Hooks

  3. Vue 3 組合 API + socket.io

  4. 使用 Firebase 和 Vue 進行文件上傳

  5. 測試..怎麼樣?!

  6. 使用 Typescript Aliases、Babel 和 TSPath 更好地導入

  7. Levensthein 算法可提供更好的造假者體驗

  1. 想要使用 React 和 GraphQL 構建應用程序?這是我們由 Karl Hadwen 提供的 1 小時免費課程

  2. 將 Redux 設置為 React 應用程序的簡單指南

  3. 使用代碼生成器搭建 Redux 樣板

  4. 使用 JavaScript 創建鍊錶