0、基本原理:逐次逼近
给定某初始解,按
若{}收敛于,且连续,则即为的解 ( )
迭代法收敛的充分条件
定理:若迭代函数满足
在区间上存在,且存在,使
则(1)、任取初值,迭代法都收敛于方程的唯一实根。
(2)、 用于误差估计
(3)、用于误差估计
例:用迭代法求方程 ,再内的根,要求,保留5位有效数字。
解:把原方程化为:
存在,且
故收敛。
为近似解。
一、牛顿迭代法解方程
原理:求解,在函数f(x)图上任何一点画一条切线,然后确定切线与x轴的交点。这个方法需要一个初始值xo,此后的迭代公式为 。具体理解:
如图,设是的一个近似根,则由泰勒展开有:,若,则可得,重复该过程,有。
matlab代码:
clear;clc;% fun = 2* x^3 - 4* x^2 + 3*x - 6;x0 = 0;error = 1;f = subs(myfunction,x0);df = subs(diff(myfunction),x0);while error > 0.0001f = double(subs(myfunction,x0));%加上double是为了显示结果为小数df = double(subs(diff(myfunction),x0));%f = sin(x0)+ x0 + 1;%df = cos(x0) + 1;root = x0 - f/df ; %牛顿迭代公式error = abs(x0 - root); %更新误差x0 = root; %更新初始值endformat longroot
调用的函数为:
function y = myfunctionsyms x;y = sin(x) + x + 1;end
syms是定义符号变量的函数,求导需要用到,没有申明的话,无法求导。
matlab中subs()是符号计算函数,表示将符号表达式中的某些符号变量替换为指定的新的变量,常用调用方式为:
subs(S,OLD,NEW) 表示将符号表达式S中的符号变量OLD替换为新的值NEW。
,加上double是为了显示结果为小数
C++代码:
/* 牛顿迭代法 求方程根 */#include <iostream>#include"function.h"using namespace std;int main(){double x0, err, e, root;cout << "请输入初始值x0, x0 = " ;cin >> x0;cout << "请输入误差限e, e = ";cin >> e;err = 10; //定义一个较大的数,使其进入循环while (err > e) {int n = 1; //迭代次数double x = x0;/*double f = 2.0 * pow(x, 3) - 4 * pow(x, 2) + 3 * x - 6;double df = 6 * pow(x, 2) - 8 * x + 3;*/double f = Original_equation(x);double df = Integral_equation(x);x = x0 - f / df;root = x;err = fabs(x0 - root);x0 = x;n++;if (n > 150) {cout << "迭代次数太多,请更换算法,已推出程序!" << endl;break;}}cout << "方程的根为:root = " << root << endl;//cout << "Hello World!" << endl;}
头文件为:
#pragma oncedouble Original_equation(double &x) {double y = 2.0 * pow(x, 3) - 4 * pow(x, 2) + 3 * x - 6;return y;}double Integral_equation(double &x) {double dy = 6 * pow(x, 2) - 8 * x + 3;return dy;}
结果为:
但是,作为计算一般性函数零解问题的算法,它有三个严重的缺陷。
要求函数必须是光滑的;可能遇到导数不方便计算的困难;初始解必须靠近准确解。
至于优点,就是对于计算平方根的问题,牛顿法特别简洁有效。
二、弦截法(弦割法)
有的时候,求导是件很麻烦的事,所以弦截法就出来了。
首先了解一下差商:称为在、两点的差商。其实在时,就是导数的定义。
原理:弦截法用最近两次选代解构造出的有限差分近似,替代牛顿法中的求导数计算,不同于牛顿法在f(x)曲线上某一点画切线的做法,它通过两个点画一条割线,下一个迭代解就是割线与x轴的交点。
割线法的迭代需要两个初始值,xo和x1,后续的迭代解按下面的公式计算:
1、定端点弦截法
、 (牛顿法中的被割线的斜率所替代)。
2、变端点弦截法
、 (牛顿法中的被割线的斜率所替代)。
matlab代码:
clear;clc;f = @(x) x^3 - x -1;x0 = 1;x1 = 1.5;k = 0;while abs(x1 - x0) > 0.0001s = (f(x1) - f(x0)) / (x1 - x0);root = x1 - f(x1) / s;x0 = x1;x1 = root;k = k + 1;if k > 150fprintf("循环次数太多,推出程序"); disp('循环次数太多,推出程序');root = NULL;break;endend% format longroot
结果为:
C++代码:
#include <iostream>#include"function.h"using namespace std;int main(){/*弦截法*/double x0, x1, error;double x ;double root;int n = 0;cout << "请输入初始值x0, x0 = ";cin >> x0;cout << "请输入初始值x1, x1 = ";cin >> x1;cout << "请输入误差限error, error = ";cin >> error;while (fabs(x1 - x0) > error) {double s = equation2(x1, x0);root = x1 - equation1(x1) / s;x0 = x1;x1 = root;n++;if (n > 150) {cout << "迭代次数太多,请更换算法,已推出程序!" << endl;break;}}cout << "方程的根为:root = " << root << endl;//cout << "Hello World!" << endl;}
头文件:
#pragma oncedouble equation1(double &x) {double y = pow(x, 3) - x - 1;return y;}double equation2(double &x1, double &x0) {double s = (equation1(x1) - equation1(x0)) / (x1 - x0);return s;}
结果为: