1.1方程求根之二分法

目录

前言

对于普通的方程,我们用高中学的解方程方法是可以的,不过对于 超越方程高次代数方程 的求解是很困难的,而且也很难得到准确得解,今天我们用Python语言和二分法来求解这些方程,得到满足精度的解,并不是准确。

(一)二分法的分析

1.定义:

在某区间有函数 \(f(x)\) 在区间\([a, b]\) 内单调连续,且\(f(a)*f(b)<0\) ,根据连续函数的性质可知方程在\([a,b]\) 内一定有唯一的实根。

2.需要满足的条件:

  1. \(f(x)\)是单调函数
  2. \(f(x)\)是连续函数
  3. \(f(a)*f(b)<0\)

3.二分法的思想:

不断的分割\([a,b]\) 区间,取\([a,b]\) 的中点值\(x=(a+b)/2\)

  1. \(f(x)*f(a)<0?\) 时,则根在\([a,x]\) 之间;
  2. \(f(x)*f(b)<0\) 时,则根在\([x,b]\) 之间。
  3. 再分割\(x=(a+b)/2\)

直到\(x\)满足我们的精度,我们取\(x\)\(f(x)\) 的近似解。

4.二分法的误差:

我们取的是:第k次分割后的中间值为近似解。

即:\(x_k=\frac{1}{2}(a_k+b_k)\)

对于预先给定的误差:\(\varepsilon>0\)

有:\(|x^*-x_k| \le \frac{1}{2}(b_k-a_k)=\frac{1}{2^k+1}<\varepsilon\)

(二)代码实现

1.算法流程图:

二分法流程图.jpg

2.源代码:

(1)feval函数:
def feval(string, a):
    """
        根据值来计算数学表达式。
    :param string: 含有x未知数的数学表达式
    :param a: 自变量x的具体数值
    :return:  数学表达式的计算结果
    """
    count = string.count("x")
    string = string.replace('x', '%f')
    t = (a, ) * count
    result = eval(string % t)
    return result
(2)二分法
"""
    二分法:
    f(a)*f(b)<0 连续函数f(a)在a,b区间必有根。
"""
from my_math.func_math import feval

def two_fun(expr, a, b, r):
    """
        二分法求解方程
    :param expr: 方程表达式
    :param a: 左端
    :param b: 右端
    :param r: 精度
    :return: 求解的结果
    """
    f_a = feval(expr, a)
    f_b = feval(expr, b)
    if f_a*f_b >= 0:
        print("该区间没有根")
    else:
        k = 0
        while 1/(2**(k+1)) > r:
            x = (b + a)/2
            if feval(expr, a) * feval(expr, x) > 0:
                a = x
            else:
                b = x
            k += 1
            print("*"*20)
            print("次数", k)
            print("x:", x)
            print("a:", a)
            print("b:", b)

    result = (a+b)/2
    print("满足精度的结果:", result)

# 求解1-x-sin(x)=0为例
if __name__ == '__main__':
    two_fun("1-x-sin(x)", 0, 1, 10**-4)

(三)案例效果

1.求解:\(1-x-sin(x)=0\)

使用二分法求解\(1-x-sin(x)=0?\) ,误差范围不超过\(\frac{1}{2}\times10^{-4}\)

(1)确定范围:

使用到数学绘图软件,根据数学表达式绘制曲线。

绘图软件的下载网址

https://www.cnblogs.com/zyg123/p/10385517.html#%E7%9B%AE%E5%BD%95

a. 大致的图像:

02.png

b.利用放大按钮,放大后的图像:

03.png

c.范围是:[0, 1]内必有根
(2)运行结果:

次数 1
x: 0.5
a: 0.5
b: 1
********************
…………


次数 13
x: 0.5108642578125
a: 0.5108642578125
b: 0.510986328125

满足精度的结果: 0.51092529296875

取结果是:0.5109

2.求解:\(sin(x)-\frac{x^2 }{4}=0\)

要求误差不超过,\(10^{-3}\)

(1)确定范围:

根据下面图像,取范围:[1.8, 2.0]

05.png

04.png

(2)运行结果:

次数 1
x: 1.9
a: 1.9
b: 2.0


…………


次数 9
x: 1.933984375
a: 1.93359375
b: 1.933984375

满足精度的结果: 1.9337890625

取结果是:1.934

3.求解:\(x^{3}-x-1=0\)

要求误差不超过:\(10^{3}\)

(1)确定范围:

根据下面图像,取范围是:[-2, 2]

06.png

07.png

(2)运行结果:

次数 1
x: 0.0
a: 0.0
b: 2.0


…………


次数 9
x: 1.3203125
a: 1.3203125
b: 1.328125

满足精度的结果: 1.32421875

取结果是:1.324
作者:Mark
日期:2019/02/17 周日

转载于:https://www.cnblogs.com/zyg123/p/10392055.html

<think>我们参考了多个来源(引用[1][2][3][4])中关于二分法方程近似的示例代码和说明。其中引用[2][3][4]提供了具体的二分法代码实现,而引用[1]则提供了数值微分方法的代码(与二分法无关)。下面将重点分析引用[2][3][4]中的二分法代码,并给出一个清晰、注释详细的二分法方程近似Python示例代码及其解释。###二分法方程近似的基本原理二分法的基本思想是:如果函数$f(x)$在区间$[a,b]$上连续,且$f(a)$与$f(b)$异号(即$f(a)\cdotf(b)<0$),则方程$f(x)=0$在区间$(a,b)$内至少有一个。通过断将区间二分,选择包含的子区间,当区间长度小于给定精度时,区间中点即可作为近似。###Python实现二分法求近似的示例代码以下代码基于引用[2][3][4]中的实现,进行了整理和注释:```pythonimportnumpyasnp#如果需要numpy,也可以用;这里使用np.abs,但也可用内建abs#定义方程f(x)=0,用户需自定义此函数deff(x):#示例方程:x^4+x^3+1=0,可修改为其他方程returnx**4+x**3+1#二分法求根函数defbisection_method(f,a,b,tol=1e-8,max_iter=1000):"""使用二分法寻找函数f在区间[a,b]上的。参数:f:函数,定义为f(x),返回一个数值。a:区间左端点。b:区间右端点。tol:容差,当区间宽度小于tol时终止迭代(默认1e-8)。max_iter:最大迭代次数(默认1000)。返回:近似,迭代次数。"""iff(a)*f(b)>=0:raiseValueError("函数在区间端点必须异号(f(a)*f(b)<0)")iter_count=0c=a#初始化中点while(b-a)>tolanditer_count< max_iter:iter_count+=1c=(a+b)/2.0#计算中点f_c=f(c)iff_c==0:#中点正好是breakeliff(a)*f_c<0:#在左半区间b=celse:#在右半区间a=creturnc,iter_count#主程序if__name__=="__main__":#设定初始区间,确保f(a)*f(b)<0a=-1.1b=-0.9try:root,n_iter=bisection_method(f,a,b)print(f"二分法的近似:{root};迭代次数:{n_iter}")exceptExceptionase:print(str(e))```###代码解释1.**定义方程**:函数`f(x)`定义了需要求解方程。示例中为$f(x)=x^4+x^3+1$,用户可据需要修改。2.**二分法函数**:`bisection_method`实现了二分法。参数包括函数`f`,初始区间`[a,b]`,容差`tol`(默认$10^{-8}$)和最大迭代次数`max_iter`(默认1000)。3.**区间验证**:首先检查`f(a)`和`f(b)`是否异号,是则抛出异常。4.**迭代过程**:-循环条件:区间宽度大于容差且迭代次数未达上限。-计算中点`c=(a+b)/2`,并求中点函数值`f(c)`。-判断中点是否为,若`f(c)=0`则退出。-否则,检查位于左半区间(`f(a)*f(c)<0`)还是右半区间,更区间端点。5.**结果输出**:返回近似和迭代次数。主程序中使用示例区间`[-1.1,-0.9]`,并处理可能异常。###注意事项-使用二分法前提:函数在区间上连续且端点函数值异号。-示例区间`[-1.1,-0.9]`对于方程$x^4+x^3+1=0$是合适的(可通过绘图或函数值验证),但方程需调整区间。-容差和最大迭代次数可据精度和效率要求调整。###引用说明以上代码和解释参考了引用[2][3][4]中有关二分法实现的内容,特别是引用[2]和[3]中代码结构以及引用[4]的教学说明[^2][^3][^4]。§§相关问题§§1.二分法收敛速度如何?如何提高二分法的效率?2.除了二分法Python中还有哪些其他方法可以求解方程的近似(例如牛顿法、弦截法)?3.如何确保初始区间选择合理?有什么方法可以确定方程在某个区间上有?</think> ### Python实现二分法求近似示例与解释 以下代码基于引用[2][3][4]的实现,结合数学原理给出详细解释: #### 核心代码 ```python def bisection(f, a, b, tol=1e-8): """二分法方程f(x)=0的近似""" n = 0 # 迭代计数器 while abs(b - a) > tol: # 区间长度大于容差时循环 n += 1 c = (a + b) / 2 # 计算中点 if f(c) == 0: # 中点恰好是 break elif f(a) * f(c) < 0: # 在左半区间 b = c else: # 在右半区间 a = c return c, n # 返回近似和迭代次数 # 示例:求方程 x^4 + x^3 + 1 = 0 在[-1.1, -0.9]的 def f(x): return x**4 + x**3 + 1 root, n_iter = bisection(f, a=-1.1, b=-0.9, tol=1e-8) print(f'近似: {root:.8f}, 迭代次数: {n_iter}') ``` #### 关键步骤解释(含数学原理) 1. **初始条件** 选择区间$[a, b]$需满足 **$f(a) \cdot f(b) < 0$**,确保据 **介值定理** 区间内存在至少一个。 2. **迭代过程** 每步计算中点 $c = \dfrac{a+b}{2}$,据函数值符号缩小区间: $$ \begin{cases} \text{if } f(a)f(c)<0 \rightarrow \text{在 } [a,c] \\ \text{if } f(c)f(b)<0 \rightarrow \text{在 } [c,b] \end{cases} $$ 几何意义:断缩小包含的正负函数值区间。 3. **终止条件** - 数学条件:区间长度 $\vert b-a \vert \leq \epsilon$ ($\epsilon$为预设容差,如$10^{-8}$) - 代码实现:`abs(b - a) > tol` 4. **收敛性** - 每步区间减半,误差上限为 $\vert x_n - r \vert \leq \dfrac{b-a}{2^n}$,其中$r$为真 - 线性收敛速度 $O(n^{-1})$,需$n \approx \log_2{\frac{b-a}{\epsilon}}$次迭代达到精度 #### 数学函数修改建议 若求解其他方程,只需修改函数定义: ```python # 示例1:求 e^x + x - 2 = 0 def f(x): import math return math.exp(x) + x - 2 # 选择区间[0,1] # 示例2:求 sin(x) - x/2 = 0 def f(x): return math.sin(x) - x/2 # 选择区间[1,3] ``` #### 优缺点分析 - ✅ 优点:实现简单、绝对收敛(只要$f$连续且初始区间满足$f(a)f(b)<0$) - ❌ 局限性: 1. 无法处理重(如$f(x)=x^2$在$x=0$处) 2. 对非单调函数可能遗漏多个 3. 比牛顿法收敛慢(牛顿法平方收敛) > 引用说明:代码结构参考了数值分析中的二分法标准实现[^2][^3],其数学原理依据连续函数的介值定理[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值