MATLAB-非线性方程的数值解法——二分法

本文主要使用MATLAB实现二分法解非线性方程的功能
二分法在用计算机求非线性方程解的数值方法中是最简单的一种,用人工算效率很低,但用计算机运算时还是一种很有效的方法。本文主要参考《计算方法》李大美 李素贞 朱方生编著

目录

  1. 原理
  2. 计算步骤
  3. 程序框图
  4. MATLAB实现
    4.1.按照程序框图进行编写
    4.2.先估算二分次数再进行二分
  5. 例题

原理

二分法的数学理论基础是闭区间上连续函数的一个基本性质,即设f(x)在闭区间[a,b]上连续且f(a)(b)<0,则在区间内至少存在一个点α,使得f(α)=0
第一步
​​​
记a0=a, b0=b, 称区间[a0, b0]为方程f(x)=0的有根区间

对分区间[a0, b0]可得中点​​​​​​ x0 并计算出f(x0)

若恰好有f(x0)=0,则方程的根为
中点
第二步
若f(x0)≠0,则计算乘积f(x0)f(b0)

1.若f(x0)f(b0)>0,则根在区间[a0, x0]内,记a1=a0,b1=x0

2.若f(x0)f(b0)<0,则根在区间[x0, b0]内,记a1=x0,b1=b0

区间[a1, b1]是包含根的新区间,在旧的有根区间内

第三步

记d1为区间[a1, b1]的长度,则d1

再将区间[a1, b1]对分,重复上述过程,可得方程新的有根区间[a2, b2],其长度为

d2

如此重复n次,若还没有找到方程的根,就得到了包含方程根的区间的一个序列:[a0, b0], [a1, b1], ···, [an, bn], ···

这个闭区间序列具有这样的特点:后一个区间落在前一个区间内,且其长度只有前一个区间长度的一半

记区间[an, bn]的长度为dn,则该区间与最初区间[a, b]的长度关系为

dn

但n充分大时,可取区间[an, bn]的中点作为方程f(x)=0的一个实根α的近似值,且它们满足关系式

误差估计式

方程根的近似值x*的绝对误差小于最初区间长度的2n+1分之一

对于给定的精度ε,可估算出二分法所需的二分次数

计算步骤

计算步骤

程序框图

程序框图

MATLAB实现

按照程序框图进行编写

有两个允许误差ε1,ε2,且未估算二分次数n

clear;clc;

%使用二分法求非线性连续函数的根,无法求复数根和偶数重根
%初始未计算二分次数

a0=1;b0=2; %输入有根区间

accuracy_1=10^(-4);accuracy_2=5*10^(-4); %设定两个允许误差

syms x; %定义变量x
f(x)=x^6-x-1; %设定方程

y1=f(a0);y2=f(b0); %求初始两端点f(x)值

a=zeros(100,1);b=a;x=a;form=zeros(100,5); %提前创建矩阵,提高运算速度,因未计算二分次数,所以设定了100次,可适当修改
if y1*y2>0
    fprintf ('区间内有偶数个根或者无实根')
else
    n=0; %n为2分次数
    a(1)=a0;b(1)=b0;
    while ((b(n+1)-a(n+1))>accuracy_2) %循环至满足误差要求
        x(n+1)=(a(n+1)+b(n+1))/2;%求当前区间中点
        y=f(x(n+1));yb=f(b(n+1)); %求此区间中点、右端点对应的f(x)
        if abs(y)<accuracy_1 %若满足第一个允许误差,即|f(x)|<ε1,填充表格并中断循环
            form(n+1,1)=n;form(n+1,2)=a(n+1);form(n+1,3)=b(n+1);form(n+1,4)=x(n+1);form(n+1,5)=y;
            break;
        else
            if y*yb>0 %y*yb大于0则让右端点等于中点,左端点保持不变,若y*yb<0则相反
                b(n+2)=x(n+1);
                a(n+2)=a(n+1);
            else
                a(n+2)=x(n+1);
                b(n+2)=b(n+1);
            end
        end
        form(n+1,1)=n;form(n+1,2)=a(n+1);form(n+1,3)=b(n+1);form(n+1,4)=x(n+1);form(n+1,5)=y; %填充表格
        n=n+1; %累计二分次数
    end
end

先估算二分次数再进行二分

先用误差估计式进行估算,求出n,再进行二分

clear;clc;

%使用二分法求非线性连续函数的根,无法求复数根和偶数重根
%初始根据误差估计式计算二分次数n

a0=1;b0=2; %输入有根区间

accuracy=5*10^(-4); %设定允许误差

syms x; %定义变量x
f(x)=x^6-x-1; %设定方程
y1=f(a0);y2=f(b0); %求初始两端点f(x)值

n=ceil(log2((b0-a0)/accuracy/2)); %由误差估计式计算二分次数,ceil:向正无穷取整
a=zeros(n,1);b=a;x=a;form=zeros(n,5); %根据二分次数提前创建矩阵,提高运算速度
if y1*y2>0
    fprintf ('区间内有偶数个根或者无实根')
else
    a(1)=a0;b(1)=b0;
    for i=1:n+1
        x(i)=(a(i)+b(i))/2;%求当前区间中点
        y=f(x(i));yb=f(b(i)); %求此区间中点、右端点对应的f(x)
        if y*yb>0 %y*yb大于0则让右端点等于中点,左端点保持不变,若y*yb<0则相反
            b(i+1)=x(i);
            a(i+1)=a(i);
        else
            a(i+1)=x(i);
            b(i+1)=b(i);
        end
        form(i,1)=i-1;form(i,2)=a(i);form(i,3)=b(i);form(i,4)=x(i);form(i,5)=y; %填充表格
    end
end

运算结果如下图

方法一
方法一
方法二
方法二

例题

求x3-x-1=0在[1, 1.5]内的解,要求ε<0.01

将a=1,b=1.5,accuracy=0.01,代码里的方程也改为x3-x-1,然后运算代码,可得图表
例题
例题参考答案
运行所得结果与例题参考答案高度重合,因此所求方程的近似解为x*=1.3203,满足允许的误差精度

  • 18
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
非线性方程数值解法: 1.二分法:对于单个非线性方程,在区间 $[a,b]$ 上使用二分法进行求解。当 $f(a) \times f(b) < 0$ 时,说明 $f(x)$ 在 $[a,b]$ 中存在零点,此时可以取区间中点 $c=(a+b)/2$,若 $f(c)=0$,则已经找到了零点;若 $f(c) \times f(a) < 0$,则零点在区间 $[a,c]$ 中,否则在区间 $[c,b]$ 中,继续使用二分法迭代求解即可。 2.牛顿法:对于单个非线性方程,使用牛顿法进行求解。设 $x_0$ 为非线性方程 $f(x)=0$ 的一个近似解,求其下一个近似解 $x_1$。根据牛顿迭代公式:$x_{n+1}=x_n-\frac{f(x_n)}{f'(x_n)}$,不断迭代直到满足精度要求。 非线性方程组的几种数值解法: 1.牛顿法:对于非线性方程组 $F(x)=0$,使用牛顿法进行求解。在每一步迭代中,需要求解 $F(x^{(k)})+J(x^{(k)})\Delta x^{(k)}=0$,其中 $J$ 为 $F$ 的雅可比矩阵,$x^{(k)}$ 为第 $k$ 步迭代的近似解,$\Delta x^{(k)}$ 为近似解的修正量,通过求解线性方程组获得。不断迭代直到满足精度要求。 2.拟牛顿法:拟牛顿法是一类使用近似 Hessian 矩阵的迭代方法。在每一步迭代中,通过近似 Hessian 矩阵求解 $\Delta x^{(k)}$,然后更新近似解 $x^{(k+1)}=x^{(k)}+\Delta x^{(k)}$。常用的拟牛顿法包括 BFGS 方法和 DFP 方法。 3.全局优化方法:对于非线性方程组,若存在多个解,使用全局优化方法进行求解。常用的全局优化方法包括遗传算法、粒子群算法、模拟退火算法等。 以下是 matlab 的源代码示例: 二分法求解单个非线性方程: ```matlab function [x, iter] = bisection(f, a, b, tol) % f: 非线性方程的函数句柄 % a, b: 初始区间 [a, b] % tol: 求解精度 % x: 方程的近似解 % iter: 迭代次数 iter = 0; while b-a > tol iter = iter + 1; c = (a+b)/2; if f(c) == 0 x = c; return; elseif f(c)*f(a) < 0 b = c; else a = c; end end x = (a+b)/2; ``` 牛顿法求解单个非线性方程: ```matlab function [x, iter] = newton(f, df, x0, tol) % f: 非线性方程的函数句柄 % df: 非线性方程的导函数句柄 % x0: 初始近似解 % tol: 求解精度 % x: 方程的近似解 % iter: 迭代次数 iter = 0; while abs(f(x0)) > tol iter = iter + 1; x0 = x0 - f(x0)/df(x0); end x = x0; ``` 牛顿法求解非线性方程组: ```matlab function [x, iter] = newton_sys(F, J, x0, tol) % F: 非线性方程组的函数句柄 % J: 非线性方程组的雅可比矩阵句柄 % x0: 初始近似解 % tol: 求解精度 % x: 方程组的近似解 % iter: 迭代次数 iter = 0; while norm(F(x0)) > tol iter = iter + 1; x0 = x0 - J(x0)\F(x0); end x = x0; ``` BFGS 拟牛顿法求解非线性方程组: ```matlab function [x, iter] = bfgs_sys(F, J, x0, tol) % F: 非线性方程组的函数句柄 % J: 非线性方程组的雅可比矩阵句柄 % x0: 初始近似解 % tol: 求解精度 % x: 方程组的近似解 % iter: 迭代次数 n = length(x0); B = eye(n); iter = 0; while norm(F(x0)) > tol iter = iter + 1; s = -B\F(x0); x1 = x0 + s; y = J(x1) - J(x0); B = B + (y'*s + s'*B*s)/(y'*y) * (y*y') - (B*s*s'*B)/(s'*B*s); x0 = x1; end x = x0; ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值