任意方程求根
全文目录
1.简介
方程和函数是代数数学中最为重要的内容之一,从初中直到大学,我们都在研究着方程与函数,甚至我们将图形代数化,从而发展出了代数几何、解析几何的内容。而在方程与函数中,我们研究其性质最多的,往往就是方程的根(零点),即使是研究方程的极值点、鞍点等,我们无非也只是研究其微商的零点。
我们在初等数学中已经学过许多简单初等函数、线性方程的求解方法,在本文中,我们重点讨论任意方程,尤其是计算困难的非线性方程的求根方法。
2.方程
2.1分类和介绍
方程就是指含有未知数的等式。是表示两个数学式(如两个数、函数、量、运算)之间相等关系的一种等式,使等式成立的未知数的值称为“解”或“根”。在这里,根据一些性质的不同,我们将方程分成以下几类:
- 单个方程
- 线性方程:本质是等式两边乘以任何相同的非零数,方程的本质都不受影响。通常认为只含有一次项的方程。
- 非线性方程:是因变量与自变量之间的关系不是线性的关系的方程。
- 多项式方程
- 超越方程:指含有未知量的超越式(指数、对数、三角函数、反三角函数等)的方程。换言之,超越方程中都有无法用含有未知数的多项式、分式或开方表示的式子。
- 多个方程
- 线性方程组
- 非线性方程组
2.2方程的零点(根、解)
若有一个值或一些值能够使得方程 f ( x ) = 0 f(x)=0 f(x)=0 成立,那么这个值就被成为方程的解,也常常被叫做零点和根。
若方程有且只有一个解 x ∗ x^* x∗,那么我们称方程有单根 x ∗ x^* x∗。
若对于方程 f ( x ) = 0 f(x)=0 f(x)=0,有 f ( x ∗ ) = 0 , f ′ ( x ∗ ) = f ′ ′ ( x ∗ ) = ⋯ = f ( k ) ( x ∗ ) = 0 , f ( k + 1 ) ( x ∗ ) ≠ 0 f(x^*) = 0,f^{'}(x^*)=f^{''}(x^*)=\cdots=f^{(k)}(x^*)=0,f^{(k+1)}(x^*)\neq0 f(x∗)=0,f′(x∗)=f′′(x∗)=⋯=f(k)(x∗)=0,f(k+1)(x∗)=0,那么称 x ∗ x^* x∗为方程的k+1重根
PS:若方程是简单幂函数多项式组成,那么方程的解的数量应和最高此项的数值一致,因为存在虚根。
3.求根方法
求根的方法基本上大同小异,都是通过区间去逼近方程的根的点。
首先我们说一个定理1:对于实函数方程 f ( x ) = 0 f(x)=0 f(x)=0,当 x ∈ ( a , b ) x\in(a,b) x∈(a,b),且 f ( x ) f(x) f(x)在 x ∈ ( a , b ) x\in(a,b) x∈(a,b)时单调且连续,若 f ( a ) ⋅ f ( b ) < 0 f(a)\cdot f(b)<0 f(a)⋅f(b)<0,则方程在 x ∈ ( a , b ) x\in(a,b) x∈(a,b)有且只有一个根。
3.1二分法
3.1.1普通二分法的原理及操作
二分法和算法中的二分搜索法非常的类似,取定有根区间 [ a , b ] [a,b] [a,b]进行对分,求得 m i d = a + b 2 mid = \frac{a+b}{2} mid=2a+b进行判断含根区间,如果 f ( a ) ⋅ f ( m i d ) < 0 f(a)\cdot f(mid)<0 f(a)⋅f(mid)<0,则令 b = m i d b=mid b=mid;反之若 f ( b ) ⋅ f ( m i d ) < 0 f(b)\cdot f(mid)<0 f(b)⋅f(mid)<0,则令 a = m i d a=mid a=mid。当 ∣ b n − a n ∣ < ϵ |b_n-a_n|<\epsilon ∣bn−an∣<ϵ停止计算返回结果。
产生的截断误差为 ∣ e n − 1 ∣ = x n + 1 − x ∗ ≤ [ b n − a n ] = b 0 − a 0 2 n |e_{n-1}| = x_{n+1} - x^*\leq[b_n - a_n] = \frac{b_0 - a_0}{2^n} ∣en−1∣=xn+1−x∗≤[bn−an]=2nb0−a0。
可以计算出最小迭代次数为 n = l g ( c 0 − a 0 ) − l g ϵ l g 2 n = \frac{lg(c_0-a_0)-lg\epsilon}{lg2} n=lg2lg(c0−a0)−lgϵ
代码实现(更多语言的代码见仓库中Code文件夹):
private static double epsilon = 0.001;
// func为函数,写法如x=>x*x+2*x-1,a,b必须为有效的含根开区间
public static double Binary(Func<double, double> func, double a, double b)
{
var f1 = func.Invoke(a);
var f2 = func.Invoke(b);
if (f1 * f2 > 0)
throw new ArgumentException("此区间无根或根不唯一");
double mid = (a + b) / (double)2;
var fm = func.Invoke(mid);
if (fm == 0)
return fm;
if (f1 * fm < 0)
b = mid;
else if (f2 * fm < 0)
a = mid;
if (Math.Abs(b - a) <= epsilon)
return (a + b) / (double)2;
return Binary(func, a, b);
}
3.1.2普通二分法准确度及速度分析
假设 [ a , b ] \left[a,b\right] [a,b]是二分法的初始区间,在进行n此二分之后,得到的最终根的分布区间 [ a n , b n ] [a_n,b_n] [an,bn]的长度为 ( b − a ) / 2 n (b-a)/2^n (b−a)/2n,我们将其中点作为根的最优估计值,与真实值之间的误差不超过区间长度的一半。
e = ∣ x c − r ∣ < b − a 2 n + 1 e = \left|x_c-r\right|<\frac{b-a}{2^{n+1}} e=∣xc−r∣<2n+1b−a
若 e < 1 2 × 1 0 − p e<\frac{1}{2}\times10^{-p} e<21×10−p,则精确到小数点后p位,
事实上我们也可以简单的计算出函数执行的次数为n+2次。
3.2浅谈迭代
3.2.1 迭代是什么
迭代是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。
重复执行一系列运算步骤,从前面的量依次求出后面的量的过程。此过程的每一次结果,都是由对前一次所得结果施行相同的运算步骤得到的。这篇文章中对于迭代有一个非常不错的概述究竟什么是迭代?
3.2.2 不动点的定义
各位可以尝试以下操作,
- 随意输入一个数字 λ \lambda λ
- 然后对其进行 c o s λ cos\lambda cosλ运算,
- 将运算结果作为新的值传回 c o s x cosx cosx函数之中
当你一直重复以上三个操作,你会发现数字最后会定格在0.73908513左右不动了。这是一个非常有趣的现象,事实上我们的这个操作就是 x n = c o s x n − 1 x_n = cosx_{n-1} xn=cosxn−1,而最后不变化的数值实际上就是 x = c o s x x = cosx x=cosx这个方程的解。
这就是我们不动点的一种实际情况,不动点原理是数学上一个重要的原理,也叫压缩映像原理或巴拿赫(Banach)不动点定理,完整的表达:完备的度量空间上,到自身的一个压缩映射存在唯一的不动点。用初等数学可以这么理解:连续映射 f f f的定义域包含值域,则存在一个 x x x使得 f ( x ) = x f(x)=x f(x)=x。
若某函数满足 f ( λ ) = λ , λ ∈ R f(\lambda)=\lambda,\lambda \in R f(λ)=λ,λ∈R,我们就称 λ \lambda λ为函数的一阶不动点。同样的,我们推广一下,若 f ( f ( λ ) ) = λ , λ ∈ R f(f(\lambda))=\lambda,\lambda \in R f(f(λ))=λ,λ∈R,则称为二阶不动点,一阶不动点必定是二阶不动点。
不动点的存在定理:若某函数 y = f ( x ) y=f(x) y=f(x)与 y = x y=x y=x存在至少一个交点,那么函数必然存在不动点。
3.2.3 函数的相似性
我们常常说图形之间的相似,事实上函数也有其相似的定义。若函数 f ( x ) f(x) f(x)对其换元,令 t = φ ( x ) , x = φ − 1 ( t ) , f ( x ) = > f ( φ − 1 ( t ) ) t = \varphi(x),x=\varphi^{-1}(t),f(x)=>f(\varphi^{-1}(t)) t=φ(x),x=φ−1(t),f(x)=>f(φ−1(t))。我们的不动点是一个基于迭代的过程,迭代就是让 f ( x 0 ) = x 1 = t , f ( x 1 ) = f ( f ( x 0 ) ) = f ( t ) = x 2 . . . f(x_0) = x_1 = t,f(x_1)=f(f(x_0))=f(t)=x_2... f(x0)=x1=t,f(x1)=f(f(x0))=f(t)=x2...的过程,如果我们换个角度去思考,迭代不就是和我们刚刚提到的换元是一个道理吗?那么我们思考一下,如果对于二次迭代 f ( f ( x ) ) f(f(x)) f(f(x)),如果说我们把函数完全看成是一个复合函数,那么我们现在需要做的就是试图将函数写成 f ( φ − 1 ( t ) ) f(\varphi^{-1}(t)) f(φ−1(t))的形式。
现在做出如下变换,将外层的 f ( x ) f(x) f(x)换元为 f ( φ − 1 ( t ) ) f(\varphi^{-1}(t)) f(φ−1(t)),那么二次迭代式就变成了 g ( t ) = φ ( f ( φ − 1 ( t ) ) ) g(t) = \varphi(f(\varphi^{-1}(t))) g(t)=φ(f(φ−1(t)))。随后对我们的 g ( x ) g(x) g(x)再进行迭代就会得到 g ( g ( t ) ) = φ ( f ( f ( φ − 1 ( t ) ) ) g(g(t)) = \varphi(f(f(\varphi^{-1}(t))) g(g(t))=φ(f(f(φ−1(t))),利用数学归纳法计算n次迭代式,那么就会得到 g n ( t ) = φ ( f n ( φ − 1 ( t ) ) ) g_n(t) = \varphi(f_n(\varphi^{-1}(t))) gn(t)=φ(fn(φ−1(t)))。
我们在这给出总结和定义:若函数 g ( x ) , f ( x ) , φ ( x ) g(x),f(x),\varphi(x) g(x),f(x),φ(x),若有 g ( x ) = φ ( f ( φ − 1 ( x ) ) ) g(x)=\varphi(f(\varphi^{-1}(x))) g(x)=φ(f(φ−1(x))),那么称函数 g ( x ) g(x) g(x)和 f ( x ) f(x) f(x)通过 φ ( x ) \varphi(x) φ(x)相似,记作 f ∼ g f\sim g f∼g, φ ( x ) \varphi(x) φ(x)称为相似的桥函数,且之前我们的过程得出了一个重要的结论就是 g ∼ f = > g n ∼ f n g\sim f=>g^n\sim f^n g∼f=>gn∼fn,同时,相似函数的不动点是完全一致的,证明如下:
若 函 数 g ( x ) 的 不 动 点 为 x 0 , 则 有 若函数g(x)的不动点为x_0,则有 若函数g(x)的不动点为x0,则有
g ( x 0 ) = x 0 = φ ( f ( φ − 1 ( x 0 ) ) ) g(x_0)=x_0=\varphi(f(\varphi^{-1}(x_0))) g(x0)=x0=φ(f(φ−1(x0)))
根 据 反 函 数 性 质 有 φ ( φ − 1 ( x ) ) = x 根据反函数性质有\varphi(\varphi^{-1}(x))=x 根据反函数性质有φ(φ−1(x))=x
故 f ( φ − 1 ( x 0 ) ) = φ − 1 ( x 0 ) = x 0 , φ − 1 ( x 0 ) 是 f ( x ) 的 一 个 不 动 点 故f(\varphi^{-1}(x_0)) = \varphi^{-1}(x_0)=x_0,\varphi^{-1}(x_0)是f(x)的一个不动点 故f(φ−1(x0))=φ−1(x0)=x0,φ−1