二分法(Bisection Method)原理及改进

非线性方程的二分法(Bisection Method)


考虑非线性方程
f ( x ) = 0 f(x)=0 f(x)=0

条件

f ( x ) ∈ C [ a , b ] f(x)\in C[a,b] f(x)C[a,b], 且 f ( a ) ⋅ f ( b ) < 0 f(a)·f(b)<0 f(a)f(b)<0

主要依据

由连续函数介值定理,则至少存在某个 x ∗ ∈ ( a , b ) x^* \in (a,b) x(a,b) ,使得 f ( x ∗ ) = 0 f(x^*)=0 f(x)=0,即 [ a , b ] [a,b] [a,b]内至少有上述方程的一个根,称 [ a , b ] [a,b] [a,b] f ( x ) f(x) f(x)的一个含根区间.并且有
∣ x ∗ − a + b 2 ∣ ≤ b − a 2 |x^*-\frac{a+b}{2}|\le\frac{b-a}{2} x2a+b2ba

二分法_1

主要思想(基本思想)

含根区间不断缩短,使含根区间之间含有一个满足误差要求的近似解。

具体过程(方法)

首先,令 a 1 = a , b 1 = b , h = b − a a_1=a,b_1=b,h=b-a a1=a,b1=b,h=ba,

  1. 找中点: x 1 = 1 2 ( a 1 + b 1 ) x_1=\frac{1}{2}(a_1+b_1) x1=21(a1+b1);

  2. 计算: f 1 = f ( x 1 ) f_1=f(x_1) f1=f(x1)(即中点的函数值);

  3. 生成含根区间:

    f ( x 1 ) = 0 f(x_1)=0 f(x1)=0,则 x ∗ = x 1 x^*=x_1 x=x1,

    f ( x 1 ) ⋅ f ( a 1 ) > 0 f(x_1)·f(a_1)>0 f(x1)f(a1)>0,则 a 2 = x 1 , b 2 = b 1 a_2=x_1,b_2=b_1 a2=x1,b2=b1,

    f ( x 1 ) ⋅ f ( a 1 ) < 0 f(x_1)·f(a_1)<0 f(x1)f(a1)<0,则 a 2 = a 1 , b 2 = x 1 a_2=a_1,b_2=x_1 a2=a1,b2=x1,
    生成含根区间 [ a 2 , b 2 ] . [ a 2 , b 2 ] [a_2,b_2].[a_2,b_2] [a2,b2].[a2,b2]满足下式:
    { ( 1 )   [ a 2 , b 2 ] ∈ [ a 1 , b 1 ] ( 2 )   b 2 − a 2 = h 2 ( 3 )   f ( a 2 ) ⋅ f ( b 2 ) ≤ 0 \left\{ \begin{aligned} (1)&\ [a_2,b_2 ]\in [a_1,b_1]\\ (2)&\ b_2-a_2= \frac{h}{2} \\ (3)&\ f(a_2)·f(b_2)\le 0 \end{aligned} \right. (1)(2)(3) [a2,b2][a1,b1] b2a2=2h f(a2)f(b2)0
    [ a 2 , b 2 ] [a_2,b_2] [a2,b2]取代 [ a 1 , b 1 ] [a_1,b_1] [a1,b1],继续以上过程,得到 [ a 3 , b 3 ] … [a_3,b_3]\dots [a3,b3]

优缺点

优点

  1. 对函数要求低(只要连续,在两个端点异号).
  2. 二分法是收敛的.

缺点

  1. 收敛速度不快,仅与公比为 1 2 \frac{1}{2} 21的等比级数的收敛速度相同.即是线性收敛的.
  2. 不能用于求偶重根、复根;不能推广到多元方程组求解.

例如:

  • x 2 = 0 , x ∈ [ − 1 , 1 ] x^2=0,x\in [-1,1] x2=0,x[1,1]
  • x 2 + 1 = 0 x^2+1=0 x2+1=0
    不能求出所有根,(即有可能漏根).
  1. 如下图,当方程 f ( x ) = 0 f(x)=0 f(x)=0存在多个根时,传统二分法最多只能找到1个根,而漏掉其余多个根.

二分法_2

改进方法

针对缺点3,对在区间 [ a , b ] [a,b] [a,b]上存在 m m m个实根的方程 f ( x ) = 0 f(x)=0 f(x)=0,拟提出如下两种改进算法:

改进方法 1

  • Step1: 通过二分法得到第一个近似根 x 1 x_1 x1;
  • Step2: 取 x 1 x_1 x1的最后一次搜索区间 [ x 1 − , x 1 + ] [x_1^-,x_1^+] [x1,x1+],考虑其端点函数值 f ( x 1 − ) f(x_1^-) f(x1) f ( x 1 + ) f(x_1^+) f(x1+)的符号;
  • Step3: 选取 f ( x 1 − ) , f ( x 1 + ) f(x_1^-),f(x_1^+) f(x1),f(x1+)与异号的区间端点函数值 f ( a ) , f ( b ) f(a),f(b) f(a),f(b)配对进行二分求根算法,分别得到两个近似根 x 2 , x 3 x_2,x_3 x2,x3;
  • Step3: 继续执行 Step2-Step3,直到找到 m m m个满足条件的根.

经检验,此算法不保证能够找出所有满足条件的根.(例如:两根之间的距离充分小)

改进方法 2

  • Step1: 对求解区间 [ a , b ] [a,b] [a,b]做网格剖分,取正整数 n n n.将 [ a , b ] [a,b] [a,b] n n n等分.记 h = b − a n ; x i = i h , 0 ≤ i ≤ n h=\frac{b-a}{n};x_i=ih,0\le i\le n h=nba;xi=ih,0in.
  • Step2: 从第一个子区间 [ x i , x i + 1 ] , i = 0 [x_i,x_{i+1}],i=0 [xi,xi+1],i=0,开始判定
    • 是否满足: f ( x i ) = 0   或 者   f ( x i + 1 ) = 0 f(x_i)=0\ 或者\ f(x_{i+1})=0 f(xi)=0  f(xi+1)=0
      • 是:得到 x i   或   x i + 1 x_i\ 或\ x_{i+1} xi  xi+1作为近似根 x i + 1 2 x_{i+\frac{1}{2}} xi+21;
      • 否:执行后续判定.
    • 是否满足: f ( x i ) ⋅ f ( x i + 1 ) < 0 f(x_i)·f(x_{i+1})<0 f(xi)f(xi+1)<0
      • 是:在区间 [ x i , x i + 1 ] [x_i,x_{i+1}] [xi,xi+1]上通过二分法得到近似根 x i + 1 2 x_{i+\frac{1}{2}} xi+21;
      • 否:继续向后判定是否满足: f ( x i ) ⋅ f ( x i + 2 ) < 0 f(x_i)·f(x_{i+2})<0 f(xi)f(xi+2)<0,直到完成对整个区间 [ a , b ] [a,b] [a,b]的判定,退出循环.
  • Step3: 选择近似根 x i + 1 2 x_{i+\frac{1}{2}} xi+21的邻近点 x i + 1 2 + x_{i+\frac{1}{2}}^+ xi+21+或者 x i + 1 2 − x_{i+\frac{1}{2}}^- xi+21 x i + 2 x_{i+2} xi+2配对执行二分法.
  • Step4: 继续执行 Step2-Step3,判断是否能够找到 m m m个满足条件的根.
    • 是:输出结果;
    • 否:加密网格( h = h 2 h=\frac{h}{2} h=2h).
  • Step5: 继续执行 Step2-Step3,直到找到 m m m个满足条件的根.

Python 代码部分

利用二分法(Bisection Method)求解在区间 [ a , b ] [a,b] [a,b]上存在 m m m个实根的方程 f ( x ) = 0 f(x)=0 f(x)=0Python代码如下:

m_roots.py:

# 开发者:    Leo 刘
# 开发环境: macOs Big Sur
# 开发时间: 2021/9/24 11:55 下午
# 邮箱  : 517093978@qq.com
# @Software: PyCharm
# ----------------------------------------------------------------------------------------------------------
"""
    主函数功能:
    寻找f(x) = sin(x)在指定区间[a,b]上的所有根
    输出区间端点函数值
    绘制函数图像
"""
import numpy as np
import matplotlib.pyplot as plt


def fun(x):
    # 方程等号左边函数f(x)

    return np.sin(x)


def sign(val):
    # 符号函数

    if val < 0:
        s = "-"

    elif val > 0:
        s = "+"

    else:
        s = "0"

    return s


def main(a, b, step=0.01):
    i = 0
    roots = []
    roots_interval = []
    root_counter = 0
    signs = ""
    # 打印f(x)的符号
    print("-" * 38)
    # print("近似解x\t\t\t函数值\t\t函数值符号")
    for x in np.arange(a, b, step):
        # print("-" * 38)
        val = fun(x)
        signs = signs + sign(val)
        # print("%.6f \t\t%.6f\t\t %s" % (x, val, sign(val)))
        if i > 0 and (signs[i - 1] == 0 or signs[i - 1] != signs[i]):
            root_counter += 1
            if signs[i - 1] == '0':
                roots = np.append(roots, x - step)
            if signs[i - 1] != signs[i] and signs[i - 1] != '0':
                roots_interval = np.append(roots_interval, x)
        i += 1

    # print("-" * 38)
    print("方程在区间[%.4f,%.4f]上根的个数为:%d" % (a, b, root_counter))
    print("准确解%d个,分别为:" % len(roots), roots)
    print("近似解%d个,所在区间分别为:" % len(roots_interval))
    for k in range(len(roots_interval)):
        print("[%.6f,%.6f]  " % (roots_interval[k] - step, roots_interval[k]), end='')

    # #  绘图
    # plt.figure(figsize=(8, 4))
    # plt.plot(np.arange(a, b, step), np.zeros_like(np.arange(a, b, step)), "k")
    # plt.plot(np.arange(a, b, step), fun(np.arange(a, b, step)), "b", label="$sin(x)$")
    #
    # plt.xlabel("$x$")
    # plt.ylabel("$f(x)$")
    # plt.title("Example")
    #
    # plt.ylim(-1.5, 1.5)
    # plt.legend()  # 显示左下角的图例
    #
    # plt.show()
    return root_counter


if __name__ == '__main__':
    main(0, 10)

m_roots.py程序运行结果:

--------------------------------------
方程在区间[0.0000,10.0000]上根的个数为:4
准确解1个,分别为: [0.]
近似解3个,所在区间分别为:
[3.140000,3.150000]  [6.280000,6.290000]  [9.420000,9.430000] 

m_roots.py程序运行结果(图示):

二分法程序运行结果

Bisection2roots_promax.py:

# 开发者:    Leo 刘
# 开发环境: macOs Big Sur
# 开发时间: 2021/9/24 5:05 下午
# 邮箱  : 517093978@qq.com
# @Software: PyCharm
# ----------------------------------------------------------------------------------------------------------

"""
    主函数功能:
    使用二分法求方程f(x) = sin(x) = 0在区间[-1,15]内的实根
    近似解的误差限EPS: 1e-6
    函数值误差限ETA: 1e-8

"""
import sys

import numpy as np


# 定义二分法类
class bisectionSolver:
    def __init__(self, a0, b0, EPS, ETA):
        """

        :param a0: 根的存在区间左端点
        :param b0: 根的存在区间右端点
        :param EPS: 近似解的误差限
        :param ETA: 函数值误差限
        """
        self.a0 = a0
        self.b0 = b0
        self.EPS = EPS
        self.ETA = ETA
        self.root_counter = 0  # 根计数器

    # 待求解非线性方程
    @staticmethod
    def fun(x):
        return np.sin(x)

    # 符号函数
    @staticmethod
    def sign(val):
        if val < 0:
            s = "-"
        elif val > 0:
            s = "+"
        else:
            s = "0"
        return s

    # 二分法求解器方法
    def bisectionSolver(self, a0, b0, EPS, ETA):
        a = np.array([a0])

        b = np.array([b0])

        # x = np.array([self.midVal(a, b)])
        x = np.array([np.mean(np.array([a, b]))])
        # 判断x0是否是解
        if np.abs(self.fun(x[0])) < ETA:
            print("    经判断,第%d步达到停止准则: |f[%.6f]| = %.6f < ETA"
                  % (1, self.fun(x[0]), ETA))
            self.root_counter += 1
            return x[0], 0
        print("二分法求解非线性方程数值结果".center(56))
        # print('-' * 66)
        # print("步数\t\t\t", "近似解\t\t\t\t\t", "解区间\t\t\t\t", "函数值")
        N = 100  # 最大迭代步
        for k in range(0, N, 1):
            # print('-' * 66)
            # print("第%d步\t\t" % (k + 1), "%.6f\t\t" % x[k], "[%.6f, %.6f]\t\t" % (a[k], b[k]), "%.6f" % self.fun(x[k]))

            fL = self.fun(a[k])

            fR = self.fun(b[k])

            fx = self.fun(x[k])

            # 决定有根子区间

            if fL * fx < 0:

                a = np.append(a, a[k])

                b = np.append(b, x[k])

                x = np.append(x, np.mean(np.array([a[k + 1], b[k + 1]])))

            elif fx * fR < 0:

                a = np.append(a, x[k])

                b = np.append(b, b[k])

                x = np.append(x, np.mean(np.array([a[k + 1], b[k + 1]])))

            if np.abs(self.fun(x[k + 1])) < ETA:
                print('-' * 66)
                print("第%d步\t\t" % (k + 2), "%.6f\t\t" % x[k + 1], "[%.6f, %.6f]\t\t" % (a[k + 1], b[k + 1]),
                      "%.6f" % self.fun(x[k + 1]))
                print('-' * 66, '\n')
                print("    经判断,第%d步达到停止准则: |f[%.6f]| = %.6f < ETA"
                      % (k + 2, x[k + 1], np.abs(self.fun(x[k + 1]))))
                self.root_counter += 1
                return x[k + 1], k + 2, a[k], b[k]

            if np.abs(self.fun(a[k + 1])) < ETA:
                print("    经判断,第%d步达到停止准则: |f[a[%d]]| = %.6f < ETA"
                      % (k + 1, k + 1, np.abs(self.fun(a[k + 1]))))
                self.root_counter += 1
                return a[k + 1], k + 1, a[k], b[k]

            if np.abs(self.fun(b[k + 1])) < ETA:
                print("    经判断,第%d步达到停止准则: |f[b[%d]]| = %.6f < ETA"
                      % (k + 1, k + 1, np.abs(self.fun(b[k + 1]))))
                self.root_counter += 1
                return b[k + 1], k + 1, a[k], b[k]

            if np.abs(a[k + 1] - b[k + 1]) < EPS:
                print('-' * 66)
                print("第%d步\t\t" % (k + 1), "%.6f\t\t" % x[k + 1], "[%.6f, %.6f]\t\t" % (a[k + 1], b[k + 1]),
                      "%.6f" % self.fun(x[k + 1]))
                print('-' * 66, '\n')
                print("    经判断,第%d步达到停止准则: b[%d] - a[%d] = %.6f < EPS"
                      % (k + 1, k + 1, k + 1, b[k + 1] - a[k + 1]))
                self.root_counter += 1
                return x[k + 1], k + 1, a[k], b[k]


# 主函数

def main(a, b, EPS, ETA):
    """

    :param a: 区间左断点
    :param b: 区间右断点
    :param EPS: 近似解的误差限
    :param ETA: 函数值误差限
    """
    bisecSolver = bisectionSolver(a, b, EPS, ETA)
    fa = bisecSolver.fun(a)
    fb = bisecSolver.fun(b)
    if fa * fb > 0:
        print("端点函数值计算结果:")
        print("f(a)=%.6f" % fa)
        print("f(b)=%.6f" % fb)
        print("f(a)*f(b)=%.6f" % (fa * fb))
        print("抱歉亲!端点函数值同号,不满足二分法启动条件,请重新输入合适的区间后运行!")
        sys.exit(1)

    if np.abs(fa) < ETA:
        print("经判断,第%d步达到停止准则: |f(a[%d])| = %.6f < ETA".center(50)
              % (0, 0, fa))
        print(f"综上,区间左端点a即为近似解: {a:.6f},此时函数值为: {bisecSolver.fun(a):.6f}")
        bisecSolver.root_counter += 1

    elif np.abs(fb) < ETA:
        print("经判断,第%d步达到停止准则: |f(b[%d])| = %.6f < ETA".center(50)
              % (0, 0, fb))
        print(f"综上,区间右端点b即为近似解: {b:.6f},此时函数值为: {bisecSolver.fun(b):.6f}")
        bisecSolver.root_counter += 1
    else:

        # 手动判断一阶导数大于零,因此有唯一解
        (x, n, a_k, b_k) = bisecSolver.bisectionSolver(a, b, EPS, ETA)
        print(f"综上,经过{n:d}次二分法搜索后, 找到近似解: {x:.6f},此时函数值为: {bisecSolver.fun(x):.6f}")


if __name__ == '__main__':
    main(-1, 15, 1e-6, 1e-8)

Bisection2roots_promax.py程序运行结果:

                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
步数			 近似解					 解区间				 函数值
------------------------------------------------------------------
第1步		 7.000000		 [-1.000000, 15.000000]		 0.656987
------------------------------------------------------------------
第2步		 3.000000		 [-1.000000, 7.000000]		 0.141120
------------------------------------------------------------------
第3步		 1.000000		 [-1.000000, 3.000000]		 0.841471
------------------------------------------------------------------
第4步		 0.000000		 [-1.000000, 1.000000]		 0.000000
------------------------------------------------------------------ 

    经判断,第4步达到停止准则: |f[0.000000]| = 0.000000 < ETA
综上,经过4次二分法搜索后, 找到近似解: 0.000000,此时函数值为: 0.000000

bisection_pro.py:

# 开发者:    Leo 刘
# 开发环境: macOs Big Sur
# 开发时间: 2021/9/25 11:39 上午
# 邮箱  : 517093978@qq.com
# @Software: PyCharm
# ----------------------------------------------------------------------------------------------------------
"""
    主函数功能:
    实现改进方法 2(张莉老师提供)的算法思想
    求解在区间$[a,b]$上存在$m$个实根的方程$f(x)=0$.
"""
import numpy as np

import Bisection2roots_promax as Br

import m_roots


# 主函数

def main(a, b, EPS, ETA):
    """

    :param a: 区间左断点
    :param b: 区间右断点
    :param EPS: 近似解的误差限
    :param ETA: 函数值误差限
    """
    print("查看解的分布情况")
    m = m_roots.main(a, b)
    print("\n", "*" * 100, "\n")
    step = (b - a) / m
    a0 = a
    b0 = a0
    roots0 = np.array([])
    bisecSolver = Br.bisectionSolver(a, b, EPS, ETA)
    while bisecSolver.root_counter < m:
        if b0 >= b:
            print("\n", "*" * 100, "\n")
            print(f"搜索步长过大,只找到{bisecSolver.root_counter:d}个(共{m:d}个)近似解,步长减半重新搜索")
            roots0 = np.array([])
            step = step / 2
            a0 = a
            b0 = a0
            bisecSolver.root_counter = 0
        b0 += step
        fa = bisecSolver.fun(a0)
        fb = bisecSolver.fun(b0)
        if fa * fb > 0:
            print("端点函数值计算结果:")
            print("f(a)=%.6f" % fa)
            print("f(b)=%.6f" % fb)
            print("f(a)*f(b)=%.6f" % (fa * fb))
            print("抱歉亲!端点函数值同号,不满足二分法启动条件,已扩大搜索区间重试!")
            continue

        if np.abs(fa) < ETA:
            print("经判断,第%d步达到停止准则: |f(a[%d])| = %.6f < ETA".center(50)
                  % (0, 0, fa))
            bisecSolver.root_counter += 1
            print(f"综上,区间左端点a即为第{bisecSolver.root_counter:d}个(共{m:d}个)近似解: {a0:.6f},"
                  f"此时函数值为: {bisecSolver.fun(a0):.6f}")
            roots0 = np.append(roots0, a0)
            a0 += (b0 - a0) / 4
            fa = bisecSolver.fun(a0)
            fb = bisecSolver.fun(b0)
            if fa * fb > 0:
                print("端点函数值计算结果:")
                print("f(a)=%.6f" % fa)
                print("f(b)=%.6f" % fb)
                print("f(a)*f(b)=%.6f" % (fa * fb))
                print("抱歉亲!端点函数值同号,不满足二分法启动条件,已扩大搜索区间重试!")
                continue
            (x, n, a_k, b_k) = bisecSolver.bisectionSolver(a0, b0, EPS, ETA)
            print(
                f"综上,经过{n:d}次二分法搜索后, 找到第{bisecSolver.root_counter:d}个(共{m:d}个)近似解: {x:.6f},"
                f"此时函数值为: {bisecSolver.fun(x):.6f}")
            roots0 = np.append(roots0, x)
            a0 = b0
            b0 = a0
        elif np.abs(fb) < ETA:
            print("经判断,第%d步达到停止准则: |f(b[%d])| = %.6f < ETA".center(50)
                  % (0, 0, fb))
            print(f"综上,区间右端点b即为第{bisecSolver.root_counter:d}个(共{m:d}个)近似解: {b0:.6f},此时函数值为: {bisecSolver.fun(b0):.6f}")
            roots0 = np.append(roots0, b0)

        else:
            (x, n, a_k, b_k) = bisecSolver.bisectionSolver(a0, b0, EPS, ETA)
            print(
                f"综上,经过{n:d}次二分法搜索后, 找到第{bisecSolver.root_counter:d}个(共{m:d}个)近似解: {x:.6f},"
                f"此时函数值为: {bisecSolver.fun(x):.6f}")
            roots0 = np.append(roots0, x)
            a0 = b0
            b0 = a0
        for k in range(len(roots0) - 1):
            if roots0[k + 1] - roots0[k] < EPS:
                print("\n", "*" * 100, "\n")
                print(f"两相邻近似解{roots0[k + 1]}与{roots0[k]}可视为同一解,步长减半重新搜索")
                roots0 = np.array([])
                step = step / 2
                a0 = a
                b0 = a0
                bisecSolver.root_counter = 0

    print(f"方程的{m:d}个近似解为:", roots0)


if __name__ == '__main__':
    main(-1, 13, 1e-6, 1e-8)

bisection_pro.py程序运行结果:

查看解的分布情况
--------------------------------------
方程在区间[-1.0000,15.0000]上根的个数为:5
准确解0个,分别为: []
近似解5个,所在区间分别为:
[-0.010000,0.000000]  [3.140000,3.150000]  [6.280000,6.290000]  [9.420000,9.430000]  [12.560000,12.570000]  
 ***********************************************************************

                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
第4步		 0.000000		 [-0.200000, 0.200000]		 0.000000
------------------------------------------------------------------ 

    经判断,第4步达到停止准则: |f[0.000000]| = 0.000000 < ETA
综上,经过4次二分法搜索后, 找到第1个(共5个)近似解: 0.000000,此时函数值为: 0.000000
                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
第22步		 3.141593		 [3.141592, 3.141593]		 -0.000000
------------------------------------------------------------------ 

    经判断,第22步达到停止准则: b[22] - a[22] = 0.000001 < EPS
综上,经过22次二分法搜索后, 找到第2个(共5个)近似解: 3.141593,此时函数值为: -0.000000
                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
第22步		 6.283185		 [6.283185, 6.283186]		 -0.000000
------------------------------------------------------------------ 

    经判断,第22步达到停止准则: b[22] - a[22] = 0.000001 < EPS
综上,经过22次二分法搜索后, 找到第3个(共5个)近似解: 6.283185,此时函数值为: -0.000000
                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
第22步		 9.424778		 [9.424777, 9.424778]		 0.000000
------------------------------------------------------------------ 

    经判断,第22步达到停止准则: b[22] - a[22] = 0.000001 < EPS
综上,经过22次二分法搜索后, 找到第4个(共5个)近似解: 9.424778,此时函数值为: 0.000000
                     二分法求解非线性方程数值结果                     
------------------------------------------------------------------
第22步		 12.566371		 [12.566370, 12.566371]		 0.000000
------------------------------------------------------------------ 

    经判断,第22步达到停止准则: b[22] - a[22] = 0.000001 < EPS
综上,经过22次二分法搜索后, 找到第5个(共5个)近似解: 12.566371,此时函数值为: 0.000000
方程的5个近似解为: [5.55111512e-17 3.14159279e+00 6.28318520e+00 9.42477760e+00
 1.25663708e+01]

数值分析与算法 - 张莉

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Matlab二分法(Bisection Method)是一种数值计算方法,用于求解方程的根。该方法的基本思路是将函数图像的两侧区域进行二分,不断缩小目标区域的范围,最终获得方程的近似解。在Matlab中,可以使用bisection函数来实现二分法。 ### 回答2: Matlab二分法是一种数值计算方法,用于找到方程的根(或零点)。它是一个迭代算法,在每轮迭代中,将区间(在该区间内由函数跨越零点)分成两个较小的子区间。算法将确定给定两个子区间中是否存在方程的根,并选择一个存在根的子区间作为新的区间,重复此过程,直到达到所需精度。 在Matlab中,使用二分法可以使用函数bisection。此函数接受以下参数: f - 为寻找根的函数句柄 a - 区间左端点 b - 区间右端点 tol - 容差 例如,下面的代码使用二分法求解方程sin(x)-x^2=0在区间[0,1]内的根: f = @(x) sin(x)-x^2; a = 0; b = 1; tol = 1e-6; [root,iter,err] = bisection(f,a,b,tol); 此代码将返回根的值,迭代次数和误差。迭代次数越少,算法就越快。但是,随着迭代次数的增加,误差也会减少。因此,选择适当的容差非常重要。如果容差过大,则可能会导致错误的解决方案。如果容差太小,则算法需要更多的迭代次数才能收敛二分法是一种经典的数值计算方法,它可以使用Matlab轻松实现。对于任何需要查找方程根的问题,二分法都是一种可靠的选择,可以在实践中非常有用。 ### 回答3: MATLAB的二分法是一种寻找实函数根的数值方法。在这种方法中,函数的根被定义为使得函数值等于零的点。对于某些函数,解析求解方法可能不存在或太复杂,因此数值方法(如二分法)能够更好地逼近函数的零点。 MATLAB中的二分法始于一个闭合区间[a, b],其中函数值的符号在端点a和b处不同。该方法的基本思想是将区间逐步缩小,直到函数值在某个位置达到所需的精度为止。对于每个区间[a, b],计算区间的中点c = (a + b) / 2,并根据函数值在c处的符号将a和b的值更新为缩小后的区间[a, c]或[c, b]。重复这个过程,直至区间的长度小于所需的精度为止。 MATLAB中的二分法通常使用while循环来实现。以下是一个简单的示例代码: function [root, n] = bisection(f, a, b, tol) % f为函数句柄,a和b为区间的端点,tol为所需的精度 % root为函数的根(即f(root)=0),n为迭代次数 if f(a)*f(b) >= 0 error('区间端点必须具有不同的函数值符号。') end n = 0; while (b-a)/2 > tol c = (a + b)/2; if f(c) == 0 root = c; % 如果中点c同时是函数的根,则直接返回根 return elseif f(c)*f(a) < 0 % 根在[a, c]之间 b = c; else % 根在[c, b]之间 a = c; end n = n + 1; % 迭代次数加1 end root = (a + b)/2; % 根为区间中点 end MATLAB的二分法具有很好的收敛性和简单的实现方式,但也存在一些局限性。例如,如果函数具有多个零点,则这种方法可能只找到其中一个,或者算法可能非常缓慢。因此,选择合适的数值方法需要根据具体的问题和函数特性进行权衡和选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图灵猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值