使用“牛顿迭代法”求解方程

article/2025/9/14 4:13:17
使用牛顿迭代法求解方程
尽管通过因式分解和利用求根公式可以很方便的得出多项式方程的根,但大多数时候这个多项式的次数都很高,计算将变得非常复杂,因此,我们必须转向一些近似解法。

牛顿迭代法是其中最好的方法之一。从根本上说,牛顿迭代法通过一系列的迭代操作使得到的结果不断逼近方程的实根。

首先,要选择一个初始值x=x0,使得该初始值接近实根的值。然后,迭代计算如下的公式:

xi+1 = xi - f(xi) / f '(xi)

直到xi+1达到一个满意的近似结果为止。在这个公式中,f(x)是要求解的多项式方程,而f '(x)是f(x)的导数。

多项式求导
多项式求导是微积分的基础,现在让我们来看看针对多项式求导的公式化描述。

要计算出多项式的求导结果,只需要对多项式的每一项套用如下两个公式:

d/dx * k = 0, d/dx *kxr = krx r-1

这里的k是为常数,r是有理数,x是未知数。符号d/dx表示求导,其中x是多项式中的变量。

对于多项式中的每一常数项,套用第一个公式;否则,就用第二个公式。假设有如下函数:

f(x) = x3 + 5x2 +3x +4

要得到求导后的结果f '(x),对该多项式的前三项套用第二个公式,最后一项套用第1个公式,得到结果如下:

f '(x) = 1 * 3x(3-1) + 5 * 2x(2-1) + 3 * 1x(1-1) + 0 = 3x2 + 10x +3

有时候也有必要进行高阶求导,即导数的导数。比如,f(x)的2阶求导可记为f ''(x),它是对f '(x)的求导结果。同理,f(x)的3阶求导可记为f '''(x),这是对f ''(x)的求导结果,以此类推。因此,在前面的例子中,如果要计算f(x)的2阶导数的话,我们按照如下的方式对f '(x)求导即可:

f ''(x) = 3 * 2x(2-1) + 10 * 1x(1-1) + 0 =6x +10

理解1阶和2阶导数
理解1阶和2阶导数的意义,是正确使用牛顿迭代法非常重要的一点。

f(x)在点x=x0处的1阶导数表示函数f(x)在点x0处的斜率。

1阶导数决定函数f(x)是递增的(从左到右上升)还是递减的(从左右到下降)。如果求导结果为正,f(x)就是递增的;而如果求导结果为负,f(x)就是递减的;如果求导结果为0,则f(x)即不是递增的也不是递减的。求导结果的大小表示f(x)递增或递减的速率。如下图所示,阴影部分表示函数的递增区间,因此这些区域里函数的1阶导数都为正值。而中间穿过横轴的部分里函数是单调递减的,因此这个区域内的1阶导数所表示的斜率都为负值。



图:函数f(x)的1阶和2阶导数的意义

f(x)在点x=x0处的2阶导数表示函数在该点处的凹凸性,也就是说函数图像是向上凸的还是向下凹的。

2阶导数值的大小表示函数图像的凹凸程度。在上图的a和c中,虚线表示函数凹凸性发生改变的位置(曲线上凸部和下凹部的分界点,也称为拐点),拐点必然是2阶导函数与x轴的交点。

另一种表示函数f(x)在某点x=c处的导数的方法是:按照点斜式表示出与f(x)相切于点c的直线方程。直线点斜式方程可写作:

y - f(c) = f ' (c)(x-c)

因此,如果f(x) = x3 - x2 - 3x + 1.8如上图a所示,那么与f(x)相切于c=1.5的直线方程就可以表示为:

y - ((1.5)3 - (1.5)2 - 3*1.5 + 1.8) = (3 * 1.52 -2 * 1.5 - 3)(x - 1.5)

y + 1.575 = 0.75(x - 1.5)

上图d中画出了这条切线。

为牛顿迭代法确定迭代初始值
牛顿迭代法中至关重要的一点是选出一个合适的初始迭代值x0。为了使牛顿迭代法能够收敛至我们要求的根,初始迭代值必须要足够接近于所求的根。下面有两条规则必须满足:

1、为x0确定一个区间[a,b],使得该区间内有且只有一个根存在。为了实现这个目的,需要选择两个值a和b,使得f(a)和f(b)的符号不同,且f '(x)的符号不会改变。如果f(a)和f(b)有不同的符号,则表示该区间内至少存在一个根。如果f '(x)的符号在区间[a,b]上不变,则可确定该区间内只包含一个根,因为该函数在此区间内只可能单调的递增或递减。

2、使x0=a或x0=b,这样f(x0)的符号就和f ''(x)在区间[a,b]上的符号相同。这也说明了f ''(x)在区间[a,b]上的符号不会改变。回顾一下,f(x)的2次导数表示函数的凹凸性,如果f ''(x)的符号不变,则f(x0)就和f ''(x)拥有相同的符号。每经过一次牛顿迭代,就会在区间[a,b]上逐步逼近于根。如下图。


图:牛顿迭代法的收敛

 在上图的4个部分中,f(x)以粗实线表示,a和b都表示为垂直的虚线。如果f(a)满足前面给出的规定,则从a开始迭代,且切线会朝着根收敛的方向倾斜。如果f(b)满足前面给定的规定,迭代就从b开始。且切线也会朝着根收敛的方向倾斜。

牛顿迭代法的工作过程
假设我们想找出方程f(x) = x3 - x2 - 3x + 1.8的根。根据函数图像(如下图),该方程会有三个根:一个在区间[-2,-1],另一个在区间[0,-1],第三个在区间[2,3]。一旦知道了方程的根的个数以及它们所在的区间,就根据上面的要求对每个区间做测试,以此挑出一个初始迭代值。要实现这一点,首先得知道如下信息:

f(x) = x3 - x2 - 3x + 1.8,f '(x) = 3x2 - 2x - 3,f ''(x) = 6x - 2

利用这些信息,我们发现[-1,-2]满足第一个要求,因为f(-2) = -4.2,f(-1) = 2.8,且f '(x)在该区间内没有改变符号(一直都是正的)。到这,我们知道在区间[-2,-1]内有且只有一个根。现在需要检查是否满足第二个要求,我们发现f ''(x)在区间上并没有改变过符号(一直都是负的)。因为f(-2)=-4.2也是负值,所以选择x0 = -2作为迭代的初始值。下图展示了在该区间内迭代计算根的过程,其精度达到了0.0001。只经过5次迭代就得到了这个近似值。


图:计算方程f(x) = x3 - x2 - 3x + 1.8 = 0的3个根的近似值,精确度0.0001

再来看看如何求出区间[0,1]上的根。我们能够看到第一个要求在该区间上是能够满足的,但是在该区间的f''(x)的符号并不是不变的,因此这个区间不能满足第二个要求。我们怀疑这个根更接近于1而不是0,因此我们接下来尝试使用区间[0.5,1],这个可以解决不满足第二个要求的问题了。f(0.5) = 0.175,f(1) = -1.2,f '(x)在这个区间内都是负值,因此第一个要求可以满足。要完成第二个要求让初始值x0 = 0.5,因为f(0.5)=0.175为正值,且同f ''(x)在区间[0.5,1]上的符号相同。上图也展示了在区间[0.5,1]上迭代计算根的过程,其精度达到了0.0001。最后用了4次迭代就达到了根的近似值。计算第3个根的过程也与此类似。

方程求解的接口定义
root
int root(double (*f)(double x), double (*g)(double x), double *x, int *n, double delta)

返回值:如果找到了根返回0;否则返回-1。

描述:采用牛顿迭代法,根据给定的初始值来计算方程f的根。初始值由x[0]指定。函数f的导数由参数g指定。参数n代表迭代的最大次数。参数delta表示逐次逼近的差值,用该值来决定何时应该结束迭代。函数返回后,迭代过程中计算出的近似值都保存在数组x中,此时n代表数组x中的元素个数。由调用者负责管理同x相关联的存储空间。

复杂度: O(n),这里n表示调用者希望进行的最大迭代次数。

方程求解的实现与分析

求解形如f(x) = 0的方程,本质上就是要找出它的根。函数root采用牛顿迭代法以给定的初始迭代值开始逐次迭代逼近,从而找到实际根。

root函数包含单个循环,该循环采用牛顿迭代公式来连续计算根的近似值。在本节给出的实现中,f就代表需要求解的方程,g代表f的导函数。每一次迭代,我们要判断当前得到的近似值是否满足需求。如果当前得到的近似值与前一轮迭代得到的近似值之差小于delta所指定的值,则认为当前的近似值满足要求。如果经过n次迭代后还是没有找到满足要求的近似根,则从函数中返回-1以表示没有找到近似根。

root函数的时间复杂度为O(n),这里n表示调用者希望进行迭代的最大次数。最坏情况是当没有找到所需要的近似根时,此时一共会进行n次迭代。
文转自:http://www.ylsjwang.com/mingxing/13.html
示例:方程求解的实现
#include <math.h>
#include "nummeths.h"


int root(double (*f)(double x), double (*g)(double x), double *x, int *n, double delta)
{
    int satisfied,i;
    
    i = 0;
    satisfied = 0;
    
    while(!satisfied && i+1 < *n)
    {
        /*x的下一个迭代值*/
        x[i+1] = x[i] - (f(x[i]) / g(x[i]));
        
        /*确定是否获得期望的近似值*/
        if(fabs(x[i+1] - x[i]) < delta)
            satisfied = 1;
        
        /*为下一次迭代做准备*/
        i++;
    }
    /*即使没有迭代,也表明一个值已经存储在x中*/
    if (i==0)
        *n=1;
    else 
        *n=i+1;
    
    /*找到实根返回0,或者达到最大迭代次数仍没有找到实根,返回-1*/
    if(satisfied)
        return 0;
    else 
        return -1;
}

http://chatgpt.dhexx.cn/article/BowJEwvk.shtml

相关文章

牛顿迭代法求解方程

说明&#xff1a;该篇博客源于博主的早些时候的一个csdn博客中的一篇&#xff0c;由于近期使用到了&#xff0c;所以再次作一总结。原文地址 概述 牛顿迭代法&#xff08;Newton’s method&#xff09;又称为牛顿-拉夫逊&#xff08;拉弗森&#xff09;方法&#xff08;Newto…

方程求根的迭代法——牛顿迭代法

用牛顿法解方程xe(x) -10 程序流程图如下&#xff1a; //方程求根的迭代法——牛顿迭代法 /*************Analysis********** *1.初值x0,精度e,迭代次数N *2.牛顿法解方程f(x)x*e**x-1 *3.取初值为0.5 ********************************/ #include<iostream> #include&…

牛顿迭代法

转自 LeetCode 解答 一篇解释得很细的文章 牛顿迭代法是一种可以用来快速求解函数零点的方法。 以 LeetCode 上的一题为例&#xff1a;模拟 int sqrt(x) 函数&#xff0c;返回的开方值向下取整。 为了叙述方便&#xff0c;我们用 C 表示待求出平方根的那个整数。显然&#xff…

牛顿迭代法(Newton’s Method)迭代求根的Python程序

迭代法的作用 许多复杂的求解问题&#xff0c;都可以转换成方程f(x)0的求解问题。这一系列的解叫做方程的根。对于非线性方程的求解&#xff0c;在自变量范围内往往有多个解&#xff0c;我们将此变化区域分为多个小的子区间&#xff0c;对每个区间进行分别求解。我们在求解过程…

用牛顿迭代法求方程的根

用牛顿迭代法求方程的根&#xff08;C语言&#xff09; 题目要求&#xff1a;牛顿迭代法是一种重要的基本的求方程根的方法。现有方程为axˆ3bxˆ2cxd0&#xff0c;系数a&#xff0c;b&#xff0c;c&#xff0c;d的值一次为1&#xff0c;2&#xff0c;3&#xff0c;4&#xff…

【源码】牛顿迭代法求根的matlab实现

牛顿迭代法求根的matlab实现 本篇是在课程学习中自己编程实现的牛顿迭代法计算非线性方程或者超越方程近似根的算法&#xff0c;写一下&#xff0c;后边便于复习和期末课程设计引用。 牛顿迭代法本质上是一种特殊的不动点迭代&#xff0c;只不过它的迭代函数的构造比较特殊&am…

牛顿迭代法求方程的根

牛顿迭代法&#xff08;牛顿-拉弗森方法&#xff09; 五次及以上多项式方程没有根式解&#xff08;就是没有像二次方程那样的万能公式&#xff09;&#xff0c;这个是被伽罗瓦用群论做出的最著名的结论。没有根式解不意味着方程解不出来&#xff0c;数学家也提供了很多方法&am…

非线性方程求根——牛顿迭代法

一、牛顿法 1.实质&#xff1a;牛顿法实质上是一种线性方法&#xff0c;其基本思想是将非线性方程f(x)0逐步归结为某种线性方程来解。 2.牛顿法公式&#xff1a; 已知方程f(x)0有近似解xk,假设&#xff0c;将f(x)在点xk泰勒展开&#xff0c;有则方程f(x)0可近似表示为&#…

C语言每日一练——第154天:牛顿迭代法求方程根

&#x1f31f; 前言 Wassup guys&#xff0c;我是Edison &#x1f60e; 今天是C语言每日一练&#xff0c;第154天&#xff01; Let’s get it&#xff01; 文章目录 1. 问题描述2. 题目分析3. 算法设计4. 确定程序框架5. 迭代法求方程根6. 代码实现 1. 问题描述 编写用牛顿迭…

前端骨架屏终极方案——骨架图

骨架图代替骨架屏。用图片代替骨架屏&#xff01;&#xff01;&#xff01; 主要还没尝试过自动生成方案&#xff0c;手工写感觉太麻烦&#xff08;美工已经操起了板砖。。。&#xff09; 最简单的实现方式&#xff0c;拿页面的UI效果图&#xff08;或者直接手机截屏&#xf…

element ui修改骨架屏形状

这是element ui的原本形状 这个形状虽然也可以 但有些情况和东西的加载显然不太适合这个形态 确实我们可以这样写 如果你是vue2 则 <div><el-skeleton animated><template slot"template"><el-skeleton-item style "width: 100vw;he…

你不可能知道的骨架屏玩法!

〇 前言 这篇是作者在公司做了活动架构升级后&#xff0c;产出的主文的前导第二篇&#xff0c;考虑到本文相对独立&#xff0c;因此抽离出单独成文。姐妹兄弟篇&#xff0c;《你可能不知道的动态组件玩法????》。 可能文“对不起”题&#xff0c;知道的大佬别进来了????…

vue加载组件骨架屏el-skeleton使用

做项目遇到的问题&#xff1a;在两个兄弟组件中&#xff0c;点击其中一个组件的一个元素&#xff0c;如button&#xff0c;会触发其兄弟组件的刷新&#xff0c; 我的做法&#xff1a;在watch中监测某字段&#xff0c;更改了之后直接在watch中发送后端请求&#xff0c;如下&…

在vue项目中使用骨架屏

现在的应用开发&#xff0c;基本上都是前后端分离的&#xff0c;前端主流框架有SPA、MPA等&#xff0c;那么解决页面渲染、白屏时间成为首要关注的点 webpack可以按需加载&#xff0c;减小首屏需要加载代码的体积&#xff1b; 使用CDN技术、静态代码等缓存技术&#xff0c;可…

使用 Vite 插件自动化实现骨架屏

大厂技术 高级前端 Node进阶 点击上方 程序员成长指北&#xff0c;关注公众号 回复1&#xff0c;加入高级Node交流群 作者&#xff1a;橙红年代 原文&#xff1a;https://juejin.cn/post/7152406737100734495 骨架屏在SPA应用中有两个显著提升用户体验的作用 避免页面初始化加…

骨架屏技术讲解以及如何在Vue中实现骨架屏

骨架屏技术讲解以及如何在Vue中实现骨架屏 写在前面骨架屏是什么如何实现&#xff08;原理分析&#xff09;一个生动的例子 实现方式&#xff08;具体实现&#xff09;方案一、在模版中来实现骨架屏方案二、使用一个Base64的图片来作为骨架屏方案三、使用 .vue 文件来完成骨架屏…

正确使用uniapp搭配微信开发者工具自带的骨架屏功能,生成骨架屏

重点&#xff1a;把index.skeleton.wxml和index.skeleton.wxss文件中的&#xff08;is““和data-event-opts””&#xff09;的整个属性删掉 一、描述&#xff1a;解决使用uniapp开发微信小程序生成骨架屏 很多人都知道微信开发者工具自带生成骨架屏的功能&#xff0c;但是却不…

vue骨架屏介绍

骨架屏可以理解为是当数据还未加载进来前&#xff0c;页面的一个空白版本&#xff0c;一个简单的关键渲染路径。可以看一下下面Facebook的骨架屏实现&#xff0c;可以看到在页面完全渲染完成之前&#xff0c;用户会看到一个样式简单&#xff0c;描绘了当前页面的大致框架的骨架…

微信小程序:骨架屏的实现方法

骨架屏是为了展示一个页面骨架而不含有实际的页面内容&#xff0c;从渲染效率上来讲&#xff0c;骨架屏它并不能使首屏渲染加快。由于骨架屏的一些使用又向用户渲染了额外的一些内容&#xff0c;这些内容是额外添加的、本来是不需要渲染的&#xff0c;它反而从整体上加长了首屏…

客户端骨架屏详解

一直以来&#xff0c;无论是Web还是iOS、Android的应用中&#xff0c;为了提升应用的加载等待这段时间的用户感知体验&#xff0c;各种技术层出不穷。其中&#xff0c;尤以菊花图以及由它衍生各种加载动画最为突出。 对于菊花图我们自不必多说&#xff0c;现在对于加载的设计体…