數據結構:遞歸:泰勒展開式(Taylor Series Expansion)

目錄

第一步:?我們要解決什么?

第二步:將其類比為求自然數和

第三步:什么是每一項?

第四步:定義要計算的每一項(term)

第五步:定義遞歸函數結構

?🌳 調用樹結構

完整代碼

復雜度分析?

🔚 總結圖(從定義到實現):?


我們將用第一性原理來一步一步推導如何用 C++ 實現泰勒展開式(Taylor Series Expansion),并借助遞歸求自然數之和的思想進行類比和遷移。

第一步:?我們要解決什么?

我們要用 C++ 寫一個函數,計算 e^x?的近似值,基于泰勒展開公式。

第二步:將其類比為求自然數和

你已經知道:

int sumOfNumbers(int n)
{if (n == 0)return 0;elsereturn sumOfNumbers(n - 1) + n;
}

我們同樣可以將泰勒級數看作是:

f(x) = 第0項 + 第1項 + 第2項 + … + 第n項

所以我們可以嘗試用遞歸方法去表達每一項,累加所有項。

第三步:什么是每一項?

我們先思考“泰勒展開”的一項的數學結構:

我們從第一性原理推導出這個公式的兩部分組成:

  • 分子是 x^n,也就是 x * x * x……(共n次)

  • 分母是 n!=n * (n?1) * (n?2)?1

所以我們必須做兩件事:

  • 每次遞歸都乘一次 x → 累計分子

  • 每次遞歸都乘一次當前 n → 累計分母

從遞歸角度重新理解:

如果你在寫一個 taylor(n) 遞歸函數,你會每次調用去表示:

  • 我要計算第 n?項,

  • 第 n?項是第 n?1 項 * x?/?n

于是我們可以這樣遞推:

? 這個推導說明:

我們不需要單獨重復計算 x^n 和 n

我們可以利用上一步的結果,乘一個新的因子 x?/?n 就能得到下一項。


第四步:定義要計算的每一項(term)

?問題來了:

如果我們想用遞歸函數一步一步計算:

double taylor(int n, double x);

那么問題是:

  • 上一項計算的結果在哪里?

  • 本層計算需要的 x^(n-1) 和 (n-1)!怎么得來?

直覺嘗試:用返回值傳信息?

你可能會嘗試每次都重新計算 x^n?和 n!,像這樣:

double taylor(int n, double x) {return taylor(n-1, x) + pow(x, n) / factorial(n);  // NOT efficient
}

問題:

  • 每一層都重復算一遍冪和階乘

  • 沒有重用信息

? 真正的優化思路:我們需要“帶狀態的遞歸”

我們希望每次調用都記住前一項計算中積累出來的 x^nn!

于是我們可以:

  • 在函數內部保留靜態變量(或全局變量)

  • 讓它在每一層遞歸中不斷更新

我們引入三個全局變量:

double num = 1; // 分子(x^n)
double den = 1; // 分母(n!)

每次遞歸做的事情就是:

  • 分子(冪函數)乘上 x

  • 分母(階乘)乘上 n

  • 計算這一項 term = num / den

  • 遞歸進入下一層(直到 n == 0 為止)

為什么不用局部變量?

  • 每一層遞歸函數自己的局部變量在返回時會銷毀,狀態無法累積。

  • 靜態/全局變量可以在整個遞歸調用鏈中持續保存狀態。

第五步:定義遞歸函數結構

我們遵循:

  • 先處理“底部終止條件”(n == 0)

  • 然后遞歸地構造前一項的和

  • 最后處理當前這一項的貢獻

否則:你將會提早計算當前項(還沒到你這一層),狀態錯位。?

Step 1:遞歸函數要怎么“停下來”?

在定義任何遞歸函數的時候,必須先回答一個問題:

? 什么時候這個函數應該“終止”,不再遞歸?

這就是我們要設定的base case(基礎情況)。

在泰勒展開中,第 0 項是已知的常數 1,所以我們在 n=0 時應該返回:1

if (n == 0) return 1;

?? 這是遞歸的“錨點”,你必須先寫,否則遞歸會無限下去。

Step 2:遞歸要先“構造前面的和”

?思維實驗:

假設你現在寫的是:

double taylor(int n, double x) {num *= x;den *= n;double res = taylor(n - 1, x);return res + num / den;
}

你發現問題了沒?

你先更新了 num 和 den,然后才去計算上一項的結果,這就打亂了狀態的對應關系——因為上一

項本來是 x^(n-1) / (x-1) !,但你已經把它提前變成 x^n?/ x?!? 了。

錯誤:我們在進入上一個遞歸之前,就已經變更了狀態!

? 正確方式:

我們應該:

  1. 先去計算 上一項的累加和(taylor(n - 1))

  2. 回來以后再更新狀態

  3. 然后把當前這一項加進去

double taylor(int n, double x) {if (n == 0) return 1;double res = taylor(n - 1, x); // 🚶先去處理前面項num *= x;                      // ?回來再乘 xden *= n;                      // ?回來再乘 nreturn res + num / den;        // ?最后加上當前這一項
}

注意!這是典型的“遞歸先深入到底部(遞歸樹的葉子)”,然后在回溯的過程中逐層累計每一項。

?🌳 調用樹結構

示例:調用 taylor(3, x),即展開 4 項 (n=3)

我們每調用一次函數,都畫出一層,并在返回時說明計算了哪一項。

                                taylor(3)↓taylor(2)↓taylor(1)↓taylor(0) ← base case = 1

然后回溯計算(從下向上):

  • 返回 taylor(0) = 1

  • 回到 taylor(1):

    • 分子 num *= x → x

    • 分母 den *= 1 → 1

    • 加項 x^1/1! = x

  • 回到 taylor(2):

    • num *= x → x2

    • den *= 2 → 2

    • 加項 x^2 / 2!

  • 回到 taylor(3):

    • num *= x → x3

    • den *= 3 → 6

    • 加項 x^3 / 3!

taylor(0) = 1
taylor(1) = taylor(0) + x / 1
taylor(2) = taylor(1) + x^2 / 2
taylor(3) = taylor(2) + x^3 / 6
回溯順序:
taylor(1) ← + x^1 / 1!     ← 分子: x,分母: 1
taylor(2) ← + x^2 / 2!     ← 分子: x2,分母: 2
taylor(3) ← + x^3 / 3!     ← 分子: x3,分母: 6

你看到沒,正是因為我們在回溯階段才處理當前項,才確保每一項都在它該在的位置!?

調用層n分子(num)分母(den)當前項?
33x^33 !=6x^3 / 6
22x^22 !=2x^2 / 2
11x1 !=1x/1
001(初始值)1(初始值)1

完整代碼

double num = 1;  // 分子
double den = 1;  // 分母double taylor(int n, double x) {if (n == 0) return 1;               // 1?? 錨點:停止遞歸double res = taylor(n - 1, x);      // 2?? 先構造前面所有項的和num *= x;                           // 3?? 然后再更新狀態den *= n;return res + num / den;             // 4?? 當前項加進去
}

復雜度分析?

這是一個非常經典的線性遞歸(linear recursion)結構。我們來詳細分析其時間復雜度和空間復雜度。?

??時間復雜度分析(Time Complexity)

我們從函數調用過程來看:

  • 調用 taylor(n) 會遞歸調用 taylor(n-1)

  • taylor(n-1) 又會調用 taylor(n-2)

  • ...

  • 最后到底部 taylor(0) 返回 1,然后逐層回溯

整個遞歸鏈條是:

taylor(n)→ taylor(n-1)→ taylor(n-2)...→ taylor(0)

總共會調用 n+1 次函數(從 0 到 n)。

每一層遞歸執行的是:

  • 一個函數調用(taylor(n - 1)

  • 兩次乘法:num *= x, den *= n

  • 一次加法:res + num / den

這些操作都是常數時間 O(1)。

?? 所以:時間復雜度為:O(n)

空間復雜度分析(Space Complexity)

這就有趣了,因為這是遞歸。

你沒有使用堆內存(比如數組、鏈表),但遞歸函數本身會在調用棧上分配幀:

  • 每調用一次 taylor(n),系統會開辟一塊棧幀來保存:

    • 參數 n, x

    • 局部變量 res

    • 返回地址

由于這個是線性遞歸(不是尾遞歸),函數不會在遞歸過程中被優化掉(除非特別啟用尾遞歸優化,C++ 一般不保證)。

?? 所以:空間復雜度為:O(n)?

🔚 總結圖(從定義到實現):?

數學定義:term_n = x^n / n!   ← 每一項都能用前一項 * (x/n) 得到遞歸目標:taylor(n) = taylor(n-1) + term_n中間狀態:num ← num * xden ← den * n于是代碼:num = 1;den = 1;double taylor(n, x) {if n==0 return 1;res = taylor(n-1, x);num *= x; den *= n;return res + num / den;}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908291.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908291.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Hadolint:Dockerfile 語法檢查與最佳實踐驗證的終極工具

在容器化應用開發的浪潮中,Dockerfile 作為構建 Docker 鏡像的核心配置文件,其質量直接影響著應用的安全性、穩定性和可維護性。然而,隨著項目復雜度的增加,手動檢查 Dockerfile 不僅耗時,還容易遺漏潛在問題。今天,我要向大家介紹一款強大的工具——Hadolint,它將徹底改…

redis數據過期策略、淘汰策略

過期鍵的刪除策略? ??1. 被動刪除(惰性刪除)?? ??觸發時機??:當客戶端嘗試訪問某個鍵時,Redis會先檢查該鍵是否過期。就是說,我們不時時檢查每個鍵是否過期,而是在使用到這個鍵時檢查是否過期&a…

ES 學習總結一 基礎內容

ElasticSearch學習 一、 初識ES1、 認識與安裝2、 倒排索引2.1 正向索引2.2 倒排索引 3、 基本概念3.1 文檔和字段3.2 索引和倒排 4 、 IK分詞器 二、 操作1、 mapping 映射屬性2、 索引庫增刪改查3、 文檔的增刪改查3.1 新增文檔3.2 查詢文檔3.3 刪除文檔3.4 修改文檔3.5 批處…

鴻蒙任務項設置案例實戰

目錄 案例效果 資源文件與初始化 string.json color.json CommonConstant 添加任務 首頁組件 任務列表初始化 任務列表視圖 任務編輯頁 添加跳轉 任務目標設置模型(formatParams) 編輯頁面 詳情頁 任務編輯列表項 目標設置展示 引入目標…

DeepSeek-R1-0528重磅升級:三大突破重新定義AI生產力

2025年5月28日,中國AI領軍企業深度求索(DeepSeek)正式發布DeepSeek-R1-0528版本,這是繼2025年1月R1模型登頂中美App Store后,DeepSeek在通用大模型領域的又一次戰略級突破。此次升級雖為小版本迭代,卻在推理…

【算法訓練營Day07】字符串part1

文章目錄 反轉字符串反轉字符串II替換數字 反轉字符串 題目鏈接&#xff1a;344. 反轉字符串 雙指針法&#xff0c;兩個指針的元素直接調轉即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …

中國西部逐日1 km全天候地表溫度數據集(TRIMS LST-TP;2000-2024)

時間分辨率&#xff1a;日空間分辨率&#xff1a;100m - 1km共享方式&#xff1a;開放獲取數據大小&#xff1a;474.31 GB數據時間范圍&#xff1a;2000-01-01 — 2024-12-31元數據更新時間&#xff1a;2025-05-31 數據集摘要 青藏高原是全球氣候變化的敏感區域。地表溫度&…

PPT轉圖片拼貼工具 v1.0

軟件介紹 這個軟件的作用就是將單個PPT的每一頁轉換為單獨的圖片&#xff0c;然后將圖片進行拼接起來。 但是我沒有還沒有解決一次性處理多個文件。 效果展示如下&#xff1a; 軟件安裝 軟件源碼 import os import re import win32com.client from PIL import Imagedef con…

嵌入式學習筆記DAY33(網絡編程——TCP)

一、網絡架構 C/S &#xff08;client/server 客戶端/服務器&#xff09;&#xff1a;由客戶端和服務器端兩個部分組成。客戶端通常是用戶使用的應用程序&#xff0c;負責提供用戶界面和交互邏輯 &#xff0c;接收用戶輸入&#xff0c;向服務器發送請求&#xff0c;并展示服務…

拋磚引玉:RadarDet4D,NuScenes數據集Radar模態目標檢測第二名(即將開源)

這幾年一直在關注自動駕駛3D目標檢測相關的研究。在NuScenes數據集上有很多經典的模型被提出并得到了驗證&#xff0c;純視覺3D目標檢測經典的方法有BEVFormer、BEVDet系列、DETR3D、Sparse4D等工作&#xff0c;基于LiDAR的有CenterPoint、多模態有BEVFusion、DAL、UniTR等。 …

更新Java的環境變量后VScode/cursor里面還是之前的環境變量

最近我就遇到這個問題&#xff0c;這個一般是安裝了多個版本的Java&#xff0c;并設置好環境變量&#xff0c;但VScode/cursor內部環境變量卻沒有改變 解決辦法 打開設置&#xff0c;或者直接快捷鍵CTRL&#xff0c;搜索Java:Home編輯settings.json文件 把以下部分改為正確的…

線程的基礎知識

進程和線程的區別&#xff1f; 從實例去引入我們的進程和線程的概念&#xff0c;說出進程和線程的關系&#xff0c;引出線程&#xff0c;說出兩者的內存分配占用&#xff0c;上下文切換的區別 當操作系統把我們磁盤中的程序加載到我們的內存當中&#xff0c;為其分配內存空間&a…

x86 匯編中的【條件跳轉指令】:從基礎到擴展的全面解析(查表版)

為了徹底覆蓋 x86 架構中所有條件跳轉指令&#xff0c;包括 8086 到現代 x86-64 的全部變體&#xff0c;我重新整理了分類體系&#xff0c;并補充了鮮為人知的指令變體、操作數大小前綴和歷史演進。 本文需要運用的知識(需要詳細了解可點擊對應的點)&#xff1a; flags寄存器…

FPGA點亮ILI9488驅動的SPI+RGB接口LCD顯示屏(一)

FPGA點亮ILI9488驅動的SPIRGB接口LCD顯示屏 ILI9488 RGB接口初始化 目錄 前言 一、ILI9488簡介 二、3線SPI接口簡介 三、配置寄存器介紹 四、手冊和初始化verilog FPGA代碼 總結 前言 ILI9488是一款廣泛應用于嵌入式系統和電子設備的彩色TFT LCD顯示控制器芯片。本文將介…

Git忽略規則.gitignore不生效解決

我在gitlab中新建了一個項目倉庫&#xff0c;先把項目文件目錄綁定到倉庫&#xff0c;并全部文件都上傳到了倉庫中。 然后又從別的項目復制了忽略文件配置過來&#xff0c;怎么搞他都不能生效忽略我不要提交倉庫的文件。 從網上查到說在本地倉庫目錄中&#xff0c;打開命…

記一個判決書查詢API接口的開發文檔

一、引言 在企業風控、背景調查、盡職調查等場景中&#xff0c;判決書查詢是一個非常重要的環節。通過判決書查詢&#xff0c;可以了解個人或企業的司法涉訴情況&#xff0c;為風險評估提供數據支持。本文將詳細介紹如何開發和使用一個司法涉訴查詢API接口&#xff0c;包括客戶…

mac版excel如何制作時長版環形圖

設置輔助列 創建簇狀柱形圖 將輔助列繪制在次坐標軸 工作時長在主坐標軸&#xff0c;右鍵分別更改圖表類型為圓環。 輔助列圓環全部為灰色&#xff0c;邊框為白色 輔助列設置透明度100% 設置輔助列和工作時長列同樣的圓環大小 可得 核心&#xff1a;只要輔助列邊框不透明…

貪心算法應用:埃及分數問題詳解

貪心算法與埃及分數問題詳解 埃及分數&#xff08;Egyptian Fractions&#xff09;問題是數論中的經典問題&#xff0c;要求將一個真分數表示為互不相同的單位分數之和。本文將用2萬字全面解析貪心算法在埃及分數問題中的應用&#xff0c;涵蓋數學原理、算法設計、Java實現、優…

量化面試綠皮書:1. 海盜分金博弈

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 1. 海盜分金博弈 五個海盜搶走了一個裝滿 100 枚金幣的箱子。作為一群民主的海盜&#xff0c;他們同意以下分配戰利品的方法:最資深的海盜將…

購物商城網站 Java+Vue.js+SpringBoot,包括商家管理、商品分類管理、商品管理、在線客服管理、購物訂單模塊

購物商城網站 JavaVue.jsSpringBoot&#xff0c;包括商家管理、商品分類管理、商品管理、在線客服管理、購物訂單模塊 百度云盤鏈接&#xff1a;https://pan.baidu.com/s/10W0kpwswDSmtbqYFsQmm5w 密碼&#xff1a;68jy 摘 要 隨著科學技術的飛速發展&#xff0c;各行各業都在…