演算法學習(17)二分法求非線性方程的解

2021-09-21 02:16:24 字數 3680 閱讀 2192

演算法學習這部分,自從離開了數論後,程式效率可提公升的地方變少了,因此看起來,好像沒意思了……換句話說,之前那種通過嘗試不同語句、不同求解思路來極大提公升程式效率的快感沒了……這好像也間接導致了我更新部落格的速度變慢了(有推脫自己三分鐘熱度的嫌疑)……

接下來這部分的內容,程式主要依賴於數學分析,而程式的主體,按著數學分析的步驟表述清楚即可,因此,分析說明會更加簡單。(寫部落格的初衷是為了督促自己持續程式設計,而不是為了寫成很詳細的說明文件,具體專題,還是要參考書籍,請諒解~)

用二分法求方程

2 x3

−5x−

1=02x^3-5x-1=0

2x3−5x

−1=0

在區間[1,

2][1,2]

[1,2

]的根,使絕對誤差不超過10−

510^

10−5

二分法:又稱對分法,最簡單的解一元非線性方程根的演算法之一。基本思路是,將含根區間i

ii 逐次分半減小,得到乙個區間長度以 i/2

i/2i/

2 的比例減小的含根區間序列 i1,

i2..

...i_1,i_2.....

i1​,i2

​...

..等絕對誤差:區間長度i

ii_i

ii​ 小於給定的限制,如本題的 10−

510^

10−5

從給定區間[a,

b][a, b]

[a,b

] 開始,驗證區間端點,一定要滿足 f(a

)∗f(

b)<

0f(a) *f(b)<0

f(a)∗f

(b)<

0, 不滿足,一般不存在根或是區間太過寬泛

取區間[a,

b][a, b]

[a,b

]中點c=a

+b2c=\frac

c=2a+b

​, 驗證 f(c

)f(c)

f(c)

是否等於0

00, 等於則 c

cc就是方程的解,退出;否則到第3步

區間縮小一半。判斷是 f(a

)∗f(

c)<

0f(a)*f(c)<0

f(a)∗f

(c)<

0 還是 f(b

)∗f(

c)<

0f(b)*f(c)<0

f(b)∗f

(c)<

0,目的是提出乘積小於0的組合,然後,把c

cc替換成a

aa 或是 b

bb; 跳到步驟2繼續執行,知道區間長度 b−a

<10

−5b-a<10^

b−a<10

−5, 跳出迴圈

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# @date : 2019-05-03 20:54:28

# @author : promise ([email protected])

# @link : $

# @version : $id$

# 用二分法求方程的關鍵是,先定義返回待計算函式值的函式,然後判斷端點的取值,從而縮小區間

import math

# 定義函式

deffunc

(x):

return

2*x*x*x -

5*x -

1# 給定根的區間,通過不斷判斷區間中點的函式值是否小於誤差,還有區間端點的精度夠不夠,從而決定是不是拿中點當解

deffindanswer

(a, b)

:# 輸入解的端點

# 正常這裡要檢查端點,先忽略了

if func(a)

* func(b)

>0:

print

('所選區間有誤,請更正!'

)# 很大程度會是錯的

return

none

middle =

(a + b)/2

while

(b-a)

>1e-

5or math.fabs(func(middle)

)>1e-

5:# 一方面是區間要小於10的負五,取值的差要衡量跟0的距離

# 更新區間

if func(middle)

* func(a)

<0:

b = middle

elif func(middle)

* func(b)

<0:

a = middle

else

:print

('所選區間不止乙個根'

) middle =

(a + b)/2

# 更新區間

return middle

defmain()

: a, b =

eval

(input

('請輸入區間端點:'))

result = findanswer(a, b)

print

('解x='

上圖是只有單獨乙個判斷條件 (b−

本圖是判斷條件有兩個(b−

a)>10

−5(b-a)>10^

(b−a

)>10

−5and ∣fu

nc(m

iddl

e)∣>1e

−5|func(middle)| > 1e-5

∣func(

midd

le)∣

>1e

−5, 第二個條件用於刻畫函式值跟零的接近程度,由於捨入誤差,我們不可能得到函式值完全等於0

00的情況,於是,只能借助不等式來表達。不過,對比上圖,二者差別其實不大。

單獨定義乙個方程求值的函式fun

c(x)

func(x)

func(x

),便於值比較 ,更高階的求解,是函式可以輸入係數,這裡從簡,省略了

在求解的主函式,判斷區間是否可用,很重要,如果區間一開始不滿足端點符號相異,接下來的求解都沒有意義。

根據實驗結果的分析,只要根的精確度在給定的區間,函式值一般不會差太多,所以增加函式值判斷的條件,可有可無

注意區間端點的更新條件

本篇部落格使用求解非線性方程最簡單額二分法進行求解,難點在於區間更新和值精確度的確定,弄懂了這兩個,就能正確求解。

演算法學習 二分法

二分查詢也稱折半查詢 binary search 它是一種效率較高的查詢方法,前提是資料結構必須先排好序,可以在資料規模的對數時間複雜度內完成查詢。但是,二分查詢要求線性表具有有隨機訪問的特點 例如陣列 也要求線性表能夠根據中間元素的特點推測它兩側元素的性質,以達到縮減問題規模的效果。舉個簡單的例子...

求方程根 (二分法)

二分法求方程的根 求下面方程的乙個根 f x x3 5x2 10x 80 0 若求出的根是a,則要求 f a 10 6 解法 對f x 求導,得f x 3x2 10x 10。由一元二次方程求根公式知方呈f x 0 無解,因此f x 恆大於0。故f x 是單調遞增的。易知f 0 0且f 100 0,所...

二分法求方程根

二分法是計算機上的一種常用演算法,下面列出計算步驟 step1 計算 step2 計算 step3 若 0,則若若 如下 erfen.m 有根區間 a,b 函式 y x 2 2 呼叫了erfenhanshu a 1 b 6 e 10 cnt 0 while e 0.1 cnt cnt 1 fa er...