FEATURED · 精选文章

微积分预备:多项式与有理函数,用SymPy夯实基础

发布时间 / 2026/9/7 14:58:22
来源 / 创域科博编辑部
栏目 / 资讯中心
微积分预备:多项式与有理函数,用SymPy夯实基础 很多人在学微积分的时候真正卡住的地方并不是极限、导数、积分这些“主角”而是预备知识没有打牢。极限要理解“变化趋势”求导本质上是在对函数做局部线性化积分则要处理“求原函数”的操作如果连函数的基本形态、运算规则和常见性质都不熟练后面每一步都会走得非常吃力。多项式与有理函数正是微积分预备知识里最不能跳过、也最值得花时间彻底搞懂的一环。这篇文章不打算干巴巴地背定义而是会讲清楚三件事多项式与有理函数在微积分里到底扮演什么角色它们的核心性质是什么以及作为程序员怎么用 Python 和 SymPy 把这些计算真正跑通。读完以后你会对“为什么泰勒展开可以用多项式逼近函数”“为什么有理函数积分要先做部分分式分解”这类微积分经典问题有一个更踏实、更具体的理解而不是只记住一个结论。我会给出可以直接运行的代码示例覆盖多项式运算、除法与余数、因式分解、求根、有理函数化简、部分分式分解以及极限、导数、积分和泰勒展开。建议你打开 Jupyter Notebook 或 VS Code边看边敲一遍。文中所有代码都尽量保持最小化方便你单独验证也方便以后作为工具函数反复使用。1. 为什么学微积分之前要先理解多项式与有理函数先下一个判断微积分的核心研究对象是函数而多项式与有理函数是所有函数类型里最容易“算到底”的两类。极限、导数、积分这些微积分操作如果作用在多项式上结果依然是多项式或非常简单的表达式如果作用在有理函数上结果也有一套系统化的处理方法。很多初学者觉得微积分难其实不是极限定义抽象而是对函数本身不熟导致看不懂题目在问什么。举一个最典型的例子泰勒展开。泰勒定理说的是一个足够光滑的函数在某个点附近可以用一个多项式来逼近而且随着多项式次数升高逼近误差会迅速减小。为什么偏偏选多项式因为多项式计算简单、求导容易、积分容易数值计算里也只需要做加法和乘法。可以说多项式是整个微积分体系里“最听话”的函数理解了它再去看指数函数、三角函数就有了对比的基准。有理函数则更贴近工程实际。控制理论里的传递函数本质上就是两个多项式之比信号处理里的滤波器设计很多也是有理函数形式。有理函数的积分是微积分课程里一个完整的专题解法套路非常固定先做多项式除法化成真分式再对分母做因式分解然后拆成部分分式逐项积分。如果不理解这部分后面学积分换元、分部积分时很容易被复杂的题目绕晕。从程序员的角度看多项式与有理函数也不只是数学课本里的概念。曲线拟合、数值插值、最小二乘法、样条曲线底层都是多项式控制系统分析、信号滤波、神经网络里的多项式逼近也都离不开这些基础函数。所以这篇文章虽然叫“微积分预备”但它带来的收益会延伸到很多实际开发场景里。还有一个容易被忽略的点微积分题目里大量出现的函数本质上都是多项式与有理函数的组合。例如求极限时常用的“抓大头”技巧依据就是多项式在无穷远处的行为由最高次项决定判断函数图像时垂直渐近线来自分母为零的点水平渐近线来自分子分母次数的比较。这些判断都不需要复杂的微积分理论只需要把多项式与有理函数的基本性质吃透。2. 多项式定义、次数与基本形态多项式Polynomial的定义可以写成一个非常整齐的形式P(x) a_n * x^n a_{n-1} * x^{n-1} ... a_1 * x a_0其中系数 a_i 是实数也可以是复数n 是非负整数。这个形式里有几个名词必须搞清楚因为它们会反复出现在微积分教材里名词含义示例P(x) 2x^3 - 5x^2 3x - 7次数degree最高次幂的指数3首项系数最高次项的系数2常数项不含 x 的项-7一次项系数x 的系数3为什么要强调次数因为很多操作的结果都直接取决于次数。两个多项式相加结果的次数不会超过两者次数的较大值两个多项式相乘结果的次数等于两者次数之和。在微积分里次数决定了一个多项式在 x 趋近正负无穷时的增长快慢也决定了它在积分后次数的变化规律。按次数分类可以给多项式一个直观的层级零次多项式常数如 P(x) 5图像是一条水平直线。一次多项式P(x) ax b图像是一条直线微积分里对应“线性函数”是导数概念的几何基础。二次多项式P(x) ax^2 bx c图像是抛物线开口方向由 a 的符号决定极值点出现在 x -b/(2a)。三次及更高次多项式图像更复杂可能出现多个极值点和拐点。在微积分预备阶段最重要的能力是看到一个多项式就能判断它的基本形状最高次项系数是正还是负决定了无穷远处函数值走向正无穷还是负无穷次数是奇还是偶决定了函数左右两端的行为是否一致。这些判断在做极限题和画函数草图时非常实用。这里也要提醒一个常见误区不要把多项式和“一元二次方程”划等号。多项式是一个表达式而方程是“多项式等于零”的约束条件。求多项式的零点也就是解对应的方程 P(x) 0这是微积分里“找函数零点”“找临界点”的基本功也是后面学习牛顿法求根、方程数值解的基础。3. 有理函数定义与定义域有理函数Rational Function的定义同样简洁它是两个多项式的比值。R(x) P(x) / Q(x)其中 Q(x) 不能是零多项式。理解有理函数首先要建立一个条件反射分母不为零。这个约束直接决定了函数的定义域也决定了函数图像上可能出现垂直渐近线的位置。例如R(x) (x^2 - 1) / (x - 1)这个函数在 x 1 处没有定义因为分母为零。很多初学者会直接把分子因式分解成 (x - 1)(x 1)然后约分得到 x 1于是认为 R(x) 就是一条直线。但严格来说R(x) 在 x 1 处仍然是未定义的它和直线 x 1 只在 x ≠ 1 时相等。这种“可去间断点”的辨析正是微积分极限章节最喜欢考察的点。有理函数还分为真分式与假分式。类比分数如果一个有理函数的分子次数小于分母次数称为真分式如果分子次数大于或等于分母次数称为假分式。任何假分式都可以通过多项式除法写成“多项式 真分式”的形式。这一步非常重要因为微积分里对有理函数求积分时第一件事往往就是做这种除法把复杂的有理函数拆成一个好处理的多项式和一个真分式。从图像上看有理函数常带有渐近线。垂直渐近线出现在分母为零且分子不为零的位置水平渐近线取决于分子分母的次数关系分子次数低于分母次数时水平渐近线是 y 0分子次数等于分母次数时水平渐近线是首项系数之比分子次数高于分母次数时没有水平渐近线但可能存在斜渐近线。这些内容在高中可能只是零散知识点但在微积分里它们是分析函数极限行为的重要工具。还有一个容易被忽略的细节有理函数经过化简后定义域不会改变。即使某个因式被约掉了原函数在那个点上的“洞”依然存在。理解这一点对后续学习连续性、可导性很有帮助因为一个函数在某点是否有定义、是否连续往往是判断它是否可导的第一步。4. 因式分解、零点与微积分的关系因式分解看起来是中学内容但它实际上是连接多项式与有理函数的桥梁也是微积分里很多技巧的源头。这里有一个核心定理必须掌握因式定理。如果多项式 P(x) 在 x a 处的值为零那么 (x - a) 一定是 P(x) 的一个因式反过来如果 (x - a) 是 P(x) 的因式那么 P(a) 0。这个定理的价值在于它把“求根”和“因式分解”变成了同一个问题的两种表达。因式分解在微积分里的第一个直接应用是求有理函数的部分分式分解。例如要计算积分∫ (3x 5) / ((x - 1)(x 2)) dx第一步就是把被积函数拆成A/(x - 1) B/(x 2)这里分母的因式分解已经提前帮我们指明了分解方向。如果分母是二次不可约因式比如 x^2 1那么部分分式的分子就要设成一次式 Ax B。这套规则在高等数学教材里有完整总结但前提是你对因式分解足够熟练。零点在微积分里的另一个应用是判断重根。如果 (x - a)^k 是多项式 P(x) 的因式就说 x a 是 k 重零点。重根与导数有直接关系一重零点处一阶导数不为零二重零点处一阶导数为零但二阶导数不为零。这个性质在研究函数极值时非常有用因为它决定了函数在零点处是“穿越”x 轴还是“相切”后返回。从数值计算的角度看求多项式的零点本身就是一个重要工程问题。高次多项式没有通用的求根公式五次及五次以上的一般多项式无法用根式求解所以数值方法如牛顿法、拉格朗日方法、特征值法就派上了用场。即使在这个阶段也建议你建立一种意识符号计算求根和数值计算求根是两条不同的路线后面在工程实践里绝大多数情况走的是数值路线。最后提醒一点因式分解不是只有“一眼看穿”一种方式。对于二次多项式可以直接用求根公式对于高次多项式可以先用因式定理试根再逐次降阶。掌握“试根法”和“多项式长除法”这两个工具很多看似复杂的分解问题都能按部就班地解决。5. 用 Python/SymPy 做多项式与有理函数运算5.1 环境准备本文的代码主要依赖 SymPy 做符号计算用 NumPy 做少量数值验证。SymPy 是 Python 生态里最流行的符号数学库可以完成因式分解、求根、化简、求极限、求导、积分等操作非常适合用来验证数学推导和理解微积分概念。pip install sympy numpy建议使用 Python 3.7 以上的版本。如果你使用的是 Anaconda 发行版SymPy 和 NumPy 通常已经内置无需额外安装。本文代码在普通 Python 脚本或 Jupyter Notebook 中都可以运行不涉及复杂的工程环境。5.2 创建多项式并进行基本运算第一个示例演示如何创建多项式、进行加减乘除运算以及计算多项式在某一点的值。import sympy as sp x sp.symbols(x) P 2*x**3 - 5*x**2 3*x - 7 Q x**2 1 print(P , P) print(P Q , sp.expand(P Q)) print(P * Q , sp.expand(P * Q)) print(P / Q , sp.simplify(P / Q)) print(P 在 x2 处的值 , P.subs(x, 2))这段代码的关键在于sp.expand。SymPy 默认会保留表达式的原始形态如果不调用expand(P Q)可能不会自动展开显示出来仍然是“未展开”的形式。sp.simplify则用于化简表达式在处理有理函数时会自动合并同类项。P.subs(x, 2)是 SymPy 中“代入求值”的标准方式它返回的是符号表达式如果希望得到浮点数可以再加一层float()转换。在实际使用中subs不仅可以代数字还可以代另一个表达式这是符号计算比普通计算器灵活的地方。5.3 除法、因式分解与求根第二个示例演示多项式除法、因式分解和求根。这里选了一个能整除的例子方便验证结果import sympy as sp x sp.symbols(x) P x**3 - 2*x**2 - 5*x 6 Q x - 1 q, r sp.div(P, Q, x) print(商 , q) print(余数 , r) print(因式分解 , sp.factor(P)) print(全部根 , sp.solve(P, x))sp.div返回两个结果商和余数。如果余数为零说明 Q 是 P 的因式这也验证了因式定理。sp.factor对多项式做因式分解sp.solve可以直接求出多项式等于零的全部根包括复数根。这个多项式可以分解为 (x - 1)(x - 3)(x 2)所以预期的输出中余数为 0根为 [1, 3, -2]。如果你手算的结果和程序输出不一致建议先用长除法核对一遍这是排查因式分解错误的经典方式。5.4 有理函数化简与部分分式分解第三个示例是本文的重点有理函数的化简和部分分式分解。部分分式分解是后续求有理函数积分的关键步骤SymPy 的apart函数可以直接完成这个操作import sympy as sp x sp.symbols(x) R (3*x 5) / ((x - 1)*(x 2)) print(化简结果 , sp.simplify(R)) print(部分分式 , sp.apart(R, x)) F (x**4 x**2 1) / (x**2 - 1) print(假分式分解 , sp.apart(F, x))第一个有理函数是典型的部分分式分解示例apart会把它拆成两个简单分式之和。如果手动计算设(3x 5) / ((x - 1)(x 2)) A/(x - 1) B/(x 2)通分后对比系数可以得到 A 8/3B 1/3。也就是说apart的输出应该是8/(3*(x - 1)) 1/(3*(x 2))这个形式。这个过程在微积分里对应的就是“把复杂积分拆成简单积分”。第二个例子是假分式。apart会先做多项式除法把假分式化为“多项式 真分式”的结构然后再对真分式做部分分式分解。最终会得到类似x^2 2 3/(2*(x - 1)) - 3/(2*(x 1))的结果其中x^2 2就是长除法得到的多项式部分。5.5 连接微积分极限、导数、积分与泰勒展开第四个示例把多项式与有理函数和微积分正式连接起来。你会发现有了前面的基础这些微积分操作就变得非常自然import sympy as sp x sp.symbols(x) f (x**2 - 1) / (x - 1) print(x→1 时的极限 , sp.limit(f, x, 1)) g x**3 - 2*x**2 x - 1 print(g 的导数 , sp.diff(g, x)) print(g 的不定积分 , sp.integrate(g, x)) print(sin(x) 在 0 处的泰勒展开 , sp.series(sp.sin(x), x, 0, 6))这段代码把前面所有概念串起来了。f (x^2 - 1)/(x - 1)在 x 1 处没有定义但极限存在且等于 2这正好对应第 3 节讲的可去间断点。diff和integrate是微积分最基础的两个操作作用在多项式上时输出仍然是多项式。series则演示了泰勒展开输出的结果是x - x^3/6 x^5/120 O(x^6)这就是用多项式逼近sin(x)的过程也是“多项式为什么重要”这个问题最直接的答案。6. 运行结果与效果验证运行完上面的代码后如何判断结果是否正确这里给出每个代码块的预期输出和判断标准。第一个代码块的预期输出中P Q展开后得到2*x**3 - 4*x**2 3*x - 6P * Q展开后是一个四次多项式。你可以用“次数等于两者次数之和”这条规则做初步验证P 是三次Q 是二次乘积应该是四次。如果看到低于四次的输出说明某个环节出了问题。第二个代码块中sp.div返回的余数为 0sp.factor输出(x - 3)*(x - 1)*(x 2)sp.solve输出[1, 3, -2]。验证方法很简单把根代回原多项式每个结果都应该是 0。也可以把分解后的因式重新乘起来确认能还原成原多项式。第三个代码块中sp.apart的输出应该与手动计算一致。手动通分是检验apart输出是否正确的可靠方法哪怕只是用 SymPy 再对结果做一次通分也可以。通分后如果能还原成原始分数形式就说明分解正确。第四个代码块的验证略特殊。sp.limit输出为 2是因为(x^2 - 1)/(x - 1)在 x 1 的邻域内等于x 1。sp.diff和sp.integrate的结果可以互相验证对导数结果再做一次积分应该能回到原函数可能相差一个常数。sp.series的结果则可以从泰勒展开公式直接核对sin(x)的麦克劳林展开前三项就是x - x^3/6 x^5/120。如果运行出现NameError通常是没有导入 SymPy 或没有定义符号 x。如果出现TypeError很可能是把字符串当成表达式传入。遇到这类问题先检查代码前几行是否执行成功再检查变量名是否一致一般就能解决。7. 常见问题与排查方法问题现象可能原因排查方式解决方案提示NameError: name sp is not defined没有导入 SymPy 或导入语句被注释检查文件头部是否有import sympy as sp补充导入语句后重新运行表达式没有自动展开输出仍是(x 1)*(x - 1)形式没有调用expand或simplify查看输出表达式是否包含括号乘积根据需求调用sp.expand或sp.simplifysolve返回空列表但图像显示有零点方程没有解析解或零点不是实数尝试用sp.solve加rationalFalse或用numpy.roots数值求根对高次多项式采用数值方法如np.roots部分分式结果和手算不一致设的形式不对或分母没有完全因式分解检查apart输出后对结果通分验证用sp.together通分并与原式比对代入求值得不到数值输出是符号表达式subs返回符号结果确认是否需要浮点数使用float(P.subs(x, 2))或P.evalf(subs{x: 2})运行代码提示内存不足或计算卡住表达式过于复杂或符号计算陷入暴力展开检查表达式是否有不必要的expand使用simplify替代部分expand或拆分步骤运行这几种情况在初学者中非常常见。前两类是使用习惯问题养成“符号计算需要显式化简”的意识后基本不会再遇到。第三类涉及符号计算与数值计算的边界值得多说一句SymPy 的solve追求精确解但高次多项式的精确解往往极其复杂实际工程中直接用 NumPy 求数值根更高效。第五类其实不算错误subs返回符号表达式是 SymPy 的默认行为很多数学推导反而希望保留精确形式。如果你想要小数用evalf或float转换即可。最后一类要特别注意符号计算的复杂度可能远超你的直觉不要在大型表达式中随意使用expand否则可能触发组合爆炸导致 Jupyter 内核卡死。8. 最佳实践与工程建议第一部分是符号计算与数值计算的选型。教学验证、数学推导、公式化简优先用 SymPy因为它保留精确结果不会引入浮点误差。但是一旦进入规模化计算比如处理上万条数据的拟合、求解大型方程组的根SymPy 的性能完全不够用应该切换到 NumPy 和 SciPy。简单总结追求精确和可读性用 SymPy追求速度和规模用 NumPy/SciPy。第二部分是高次多项式的数值稳定性问题。直接用numpy.roots求一个次数很高的多项式零点往往会得到不稳定的结果因为多项式系数的微小扰动可能让根发生巨大变化。更稳妥的做法是尽量不展开多项式而是使用零点形式或者改用其他数值算法比如基于伴随矩阵的特征值法。在工程实践中尽量避免手动展开高次多项式保持因式形式或使用专业数值库。第三部分是计算效率问题。多项式求值有一个经典的优化技巧霍纳方法Horners Method。按照从高次到低次的顺序不断乘 x 再加下一个系数可以大幅减少乘法次数。这个技巧在嵌入式计算、信号处理中非常实用它和理解多项式结构是同一件事把多项式写成嵌套形式而不是展开形式。第四部分是命名与代码组织。符号计算脚本虽然短但建议把“符号定义、表达式定义、计算操作、结果输出”四部分分开写不要混在一起。一个常用的做法是把经常要用的多项式操作封装成函数例如import sympy as sp x sp.symbols(x) def factor_and_roots(expr): factored sp.factor(expr) roots sp.solve(expr, x) return factored, roots P x**3 - 2*x**2 - 5*x 6 factored, roots factor_and_roots(P) print(因式分解:, factored) print(根:, roots)第五部分是数学实践建议。在学习微积分预备知识时不要只满足于“代码能跑出结果”建议每跑一个示例都先用笔在纸上手动算一遍再用程序验证。尤其是部分分式分解手算和程序对照一次比你刷十道题更有效。这个过程建立的是数学直觉而代码只是一个加速验证的工具。还有一个值得养成的习惯把 SymPy 当成计算器来验证自己的作业和推导。遇到不确定的因式分解、极限、积分结果先用代码跑一遍再回到纸上分析原理。很多开发者数学基础不扎实不是理解能力不够而是缺少一个可以随时验证的工具SymPy 恰好补上了这个缺口。9. 总结与后续学习方向这篇文章围绕“微积分预备”中的多项式与有理函数讲清楚了它们为什么重要、有哪些核心性质、如何用 Python 和 SymPy 做计算验证。核心知识点包括多项式的次数与形态判断、零点和因式定理、有理函数的定义域与渐近线、假分式与真分式的转换、部分分式分解以及这些概念在极限、导数、积分和泰勒展开中的直接应用。建议你下一步做两件事。第一把这篇文章里的四个代码示例全部跑一遍逐个验证输出结果尤其要把“部分分式分解”和“泰勒展开”两个例子手动推导一次。第二继续补充另外几类基本初等函数的知识包括指数函数、对数函数和三角函数它们是微积分里另一条重要主线也是后续学习换元积分法、分部积分法时绕不开的基础。多项式与有理函数是微积分这座大厦的地基。地基打牢了极限、导数、积分学起来会顺畅很多地基不稳后面很容易遇到“每个字都认识但题目完全不会做”的困境。把代码收藏备用学到有理函数积分和泰勒展开的时候再翻回来跑一遍你会发现当时的理解又深了一层。
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻