root
root
找到確切的輸入數值,讓輸出數值是零,稱作「求根」。這樣的輸入,稱作「根」,可能有許多個、也可能不存在。
以函數圖形表達函數的根:當輸入變數只有一個,是函數曲線與X軸的相交之處。當輸入變數只有兩個,是函數曲面與XY平面的相交之處。當輸入變數有許多個,請讀者自行推廣。
中學數學談過多項式函數的求根,相信大家印象深刻。比如一元二次多項式函數的求根(解一元二次多項式方程式),有個號稱數學界最難背的公式:二a分之負b正負根號b平方減四ac。
_________ -b ± V b² - 4ac x = ——————————————— 2a
以下則是談一般的函數的求根。多項式函數,性質優美,擁有特定公式;一般的函數,雜亂無章,沒有固定公式,只好利用電腦了。最簡單的求根演算法,就是窮舉法:窮舉各種輸入,看看輸出是不是零。
窮舉法非常慢。接下來介紹更快的方法。
root: bisection method
用途
用來找到連續函數的根。bi-這個字首是「雙」的意思,而section是「分段」的意思。中文譯作「二分法」。
勘根定理
解釋演算法之前,得先複習一下高中數學的「勘根定理」。
連續函數的圖形當中,當起點與終點分別在X軸的兩側,那麼一定在某處穿過X軸。換句話說,在某處有根。換句話說,至少有一個根。
以數學符號說明勘根定理
連續函數f(x),任意區間[a,b]。a和b分別代入f(x),得到f(a)和f(b)。
如果f(a)和f(b)是一正一負、是異號,即f(a) f(b) < 0,就表示座標(a, f(a))和座標(b, f(b))這兩點位於X軸的兩側。因為f是連續函數,所以座標(a, f(a))到座標(b, f(b))的路線,一定碰到X軸至少一次──區間[a,b]裡面至少有一個根。
如果f(a)和f(b)是同號,即f(a) f(b) > 0,就表示座標(a, f(a))和座標(b, f(b))這兩點位於X軸的同側──區間[a,b]裡面可能有根,也可能無根。
如果f(a)和f(b)有零,即f(a) f(b) = 0,此時a和b就是根──區間[a,b]裡面可能還有其他根,也可能無根。
另外,當[a,b]的端點恰好沒有定義在f(x)當中,則無法計算出f(a)和f(b)的值。要解決這個問題,可以將區間略微縮小一些,像是[a + 0.001, b - 0.001],即可避免端點沒有定義的情況。
二分法
區間切兩半,縮小區間,夾擠根,逼近根。
遞迴下去,直到區間足夠微小。
找到一個根
左右兩個區間都處理,結果跟窮舉法沒兩樣。
不如只處理其中一個區間吧!只處理確定有根的區間,即f(a)和f(b)異號的區間。如果左右兩個區間都確定有根,那麼就只處理左邊區間。這正是binary search。
f(a)和f(b)同號的區間,放棄處理,不確定是否有根。f(a)和f(b)為零的區間,中止處理,顯然已經找到一個根。f(a)和f(b)異號的區間,繼續處理,二分尋找根。
最小精確度
二分越多次,答案越精確。
float變數、double變數,能夠儲存的位數有限,不可能精確,有著一個極限。不斷分割區間,就能到達極限。一個float變數的範圍約為10³⁸到10⁻³⁸,分割區間log₂10⁷⁶ ≈ 252次,定能得到float變數所能儲存的最精確的數值。
據我測試,不管迴圈計算多少遍,a b的大小關係永遠不變,而c永遠會在[a,b]當中,不會超出範圍。
迴圈不斷計算之後,有些函數造成a b最終相等,也有些函數造成a b永遠不相等,永遠相差一個最小精確度的值。要解決不相等的問題,只需判斷c是a或是b即可。
自訂精確度
[a,b]寬度大於自訂精確度,就繼續分割區間。[a,b]寬度小於等於自訂精確度,就立即停止迴圈。因為c永遠在[a,b]當中,所以c的誤差不超過自訂精確度。
如此一來,得以減少迴圈次數,不必做到252次。
找到所有根
整條數線細分成許多微小區間。f(a)和f(b)同號的區間,視作沒有根;f(a)和f(b)為零的區間,視作只有端點有根;f(a)和f(b)異號的區間,視作剛好有一個根,實施二分法找到根。
只要細分的足夠細膩,理論上可以找到所有根,除了一種例外:根恰好是局部極值。此時必須配合其他的求根方法,才能處理這個例外。
範例:求平方根
遞增函數
連續遞增(減)函數,若有根,保證能找到根。
二分法不斷地縮小根的範圍。
root: Newton's method
牛頓法
一張圖勝過千言萬語。
範例:求平方根
x = sqrt(n) x² = n x² - n = 0 f(x) = x² - n f′(x) = 2x
凸函數
斜率是連續遞增(減)函數,若有根,保證能找到根。
以斜率的觀點來看,牛頓法不斷地縮小斜率範圍。
root: secant method
割線法
牛頓法採用切線,割線法採用割線。
缺點:遞推次數更多、計算步驟更多。優點:不用微分。
一開始選定的兩點,如果不夠靠近根,割線可能會亂跑。
運氣不好時,割線呈水平線,割線法會故障;割線趨近水平線,下一點會溢位。
fixed point
fixed point(fixpoint)
找到確切的輸入數值,讓輸出和輸入完全一樣。這樣的輸入稱作「不動點」。可能有許多個,也可能不存在。
以函數圖形表達函數的不動點:當輸入變數只有一個,是函數曲線與直線y = x的相交之處。當輸入變數超過一個,此處不討論。
eigenpoint【尚無正式名稱】
找到確切的輸入數值,讓輸出是輸入的倍數,倍數是某個定值。這樣的輸入稱作「特徵點」。可能有許多個,也可能不存在。
以函數圖形表達函數的特徵點:當輸入變數只有一個,是函數曲線與直線y = λx的相交之處。當輸入變數超過一個,此處不討論。
求根、求不動點、求特徵點,本質上是同一件事情。
求根變成求不動點:等號兩邊同時加上x。求不動點變成求根:等號兩邊同時減去x。
f(x) = 0 <---> f(x) + x = x <---> g(x) = x
求根變成求特徵點:再乘上任意倍率。求特徵點變成求根:反向操作。
f(x) = 0 <---> λ (f(x) + x) = λx <---> h(x) = λx
只要知道怎麼求不動點、特徵點,就能求根。碰巧的是,不動點擁有高速演算法!
fixed point: fixed point iteration
不動點遞推法
不斷代入上次求得的數值。就這麼簡單。
即是在函數圖形與45°斜線之間往返。越走越小圈、越走越近。
運氣不好時,無法得到不動點。
越走越大圈、越走越遠。
程式碼很短,只有一個迴圈。
收縮函數:斜率絕對值小於1的連續函數
遭遇不動點,其中一種情況,就是步伐越來越短。測量X軸方向的步伐大小,即是x₀ x₁ x₂……之間的間距。當間距越來越小,最後xₜ = xₜ₊₁ = f(xₜ)趨近相等,遭遇不動點xₜ。
此處只討論這種情況。
|x₁ - x₀| > |x₂ - x₁| > |x₃ - x₂| > ...... |x₁ - x₀| > |x₂ - x₁| 此處以開頭兩項為例。事實上任意相鄰兩項都成立。 |x₁ - x₀| > |f(x₁) - f(x₀)| |f(x₁) - f(x₀)| 1 > ——————————————— = |slope| |x₁ - x₀| |slope| < 1 -1 < slope < 1
先後間距變小,移項之後,割線斜率介於±1。
也就是說,一個連續函數,任意兩點的割線的斜率的絕對值都小於1,保證有不動點。無論起點在哪裡,都能找到不動點。
換句話說,切線的斜率的絕對值都小於1。不太斜的連續函數。
特徵點遞推法
在函數圖形與斜率λ的直線之間往返。上次求得的數值,除以λ之後才代入。
平緩函數:斜率絕對值小於|λ|的連續函數
遭遇特徵點,其中一種情況,就是步伐越來越短。中略。割線的斜率介於±λ。
|x₁ - x₀| > |x₂ - x₁| > |x₃ - x₂| > ...... |x₁ - x₀| > |x₂ - x₁| 此處以開頭兩項為例。事實上任意相鄰兩項都成立。 |x₁ - x₀| > |f(x₁/λ) - f(x₀/λ)| 上次求得的數值,除以λ之後才代入。 |λχ₁ - λχ₀| > |f(χ₁) - f(χ₀)| 變數代換 |λ| |χ₁ - χ₀| > |f(χ₁) - f(χ₀)| |f(χ₁) - f(χ₀)| |λ| > ——————————————— = |slope| |χ₁ - χ₀| |slope| < |λ| -|λ| < slope < |λ| 介於±λ
equation
equation
由未知數(變數)、已知數(常數)的各種運算來構成式子。兩個相等的式子,就叫作「方程式」。
2x + 1 = (4x² + 3) / (x - 1)
方程二字借自中國古代數學書籍,意義相去甚遠,是個不精準的翻譯。按照英文字面意義來翻譯,應該稱作「等式」才對。
中學數學教了很多方程式的計算,例如解一元二次方程式、解聯立方程式,並且搭配幾何學一起講解。大學指考前,算了千百次,應當難不倒各位。
方程式有什麼用途呢?其實就是設x、解x。這兩件事情很難用中文講個明白,不過只要經歷許多數學題目之後,自然而然就能體會到設x、解x的精神所在。
求根、求不動點、求特徵點、求解,本質上是同一件事情。
方程式重新整理成函數的模樣,就能求解。
2x + 1 = (4x² + 3) / (x - 1) 等量減法公理,兩邊同減一樣多的東西。(移項) 2x + 1 - (4x² + 3) / (x - 1) = 0 整理成函數的模樣,然後求根即可! f(x) = 2x + 1 - (4x² + 3) / (x - 1)
方程式重新整理成函數的模樣,就能以各種姿勢求解。
f(x) = 0 root f(x) + x = x ---> g(x) = x fixed point λf(x) + λx = λx ---> h(x) = λx eigenpoint λf(x) + λq(x) = q(x) ---> p(x) = q(x) solution
UVa 358 10341 10428 10566 10668 11277
容易求根、求不動點、求特徵點、求解的函數類型
increasing function:遞增函數。輸入變大,輸出跟著變大(或不變)。斜率是正數(或零)。適合bisection method。
convex function:凸函數。隨便劃一道割線,函數曲線總是凹下去(或平貼)。斜率是遞增函數。適合Newton's method。
Lipschitz function:平緩函數。隨便劃一道割線,斜率的絕對值小於(或等於)一個定值。適合fixed point iteration。
polynomial function:多項式函數。可以手工推導公式解,也可以使用上述演算法求解。
大家習慣改成嚴格版本、去掉等號,讓函數曲線不會平貼座標軸、不會產生無限多根。
system of equations(simultaneous equations)
許多道方程式同時成立,整體稱作「方程組」或者「聯立方程式」。
⎧ 1 x + 2 y - 4 sin(z) = 1 ⎨ 2 x - 4 y + 2 cos(z) = 2 ⎩ 3 x + 1 y + 1 exp(z) = 3
inequality
inequality(inequation)
「不等式」。等號=改成了小於<、大於>、小於等於≤、大於等於≥、不等於≠。
2x + 1 < (4x² + 3) / (x - 1)
system of inequalities
「不等式組」、「聯立不等式」。許多道不等式同時成立。
⎧ 1 x + 2 y - 4 sin(z) < 1 ⎨ 2 x - 4 y + 2 cos(z) ≤ 2 ⎩ 3 x + 1 y + 1 exp(z) > 3
不等式可以重新整理成函數的模樣。
大於可以重新整理成小於。
⎧ 1 x + 2 y - 4 sin(z) - 1 < 0 ⎧ f(x,y,z) < 0 ⎨ 2 x - 4 y + 2 cos(z) - 2 ≤ 0 ---> ⎨ g(x,y,z) ≤ 0 ⎩ -3 x - 1 y - 1 exp(z) + 3 < 0 ⎩ h(x,y,z) < 0
constraint satisfaction
「約束滿足」。許多道等式與不等式同時成立。