数据结构:递归:泰勒展开式(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 → x²

    • den *= 2 → 2

    • 加项 x^2 / 2!

  • 回到 taylor(3):

    • num *= x → x³

    • 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!     ← 分子: x²,分母: 2
taylor(3) ← + x^3 / 3!     ← 分子: x³,分母: 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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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;各行各业都在…