一、实验内容
二、实验过程
(一)非线性方程求根
1.定理
高于4次的代数方程无精确的求根公式。
2.方法
①二分法②不动点迭代法③牛顿迭代法④弦截法⑤黄金值分割法
(二)二分法
1.定义
用近似方法求方程的根需要知道方程的根所在区间
隔根区间:如果在区间[a, b]内只有方程f(x)=0的一个根,则称[a, b]为隔根区间。
2.二分法的基本思想
通过计算隔根区间的中点,逐步将隔根区间缩小,从而可得方程的近似根。
二分检索和二分法很相似,不过二分查找要求数组有序,在非线性方程求根里面就是要求函数单调。不过二分搜索不要求函数单调。因为随着区间长度减半,如果能够求出满足精度的近似解,不断减半的区间内,函数终会单调。
二分法只适合求单根,在有根区间内只能存在一个根才行。在给定的有根区间上应用二分法总是可以得到足够精确的近似根。但随着有根区间的缩小,精度提高的越来越慢。所以二分法通常用于求其它算法的初始近似根。
3.步骤
设f(x)=0的隔根区间是[a, b],且f(a)<0, f(b)>0。
(1) 输入a, b, eps,计算f(a)
(2) 计算x=(a+b)/2,若f(a)* f(x)<0,则b=x,否则a=x
(3) 若|a-b|<eps,则停止循环,x即为所求根,否则转(2)
4.代码
//二分法
//a是隔根区间左边界,b是右边界,eps是误差,m是最大迭代次数
double Bisection(double f(double x), double a, double b, double eps,int *m)
{
double x1, x2, mid;
x1 = a;
x2 = b;
do
{
mid = (x1 + x2) / 2;// 算中值
if (f(x1) * f(mid) < 0)
{
x2 = mid;
}
else if (f(x2) * f(mid) < 0)
{
x1 = mid;
}
(*m)--;
} while (fabs(f(mid)) >= eps&&*m);// 递归计算
return x2;
}
5.优缺点
优点:运算简单,易于实现。对函数f(x)要求不高,只要求其在[a, b]上连续。
缺点:不能用于求复根及偶数重根。收敛速度较慢(因为每步误差是以1/2因子下降)。
(三)不动点迭代法
1.简单迭代法
2.基本思想
几何含义:求曲线y=g(x)和y=x的交点
3.步骤
①给出方程的局部等价形式
②取适合的初值x0
③计算x1=g(x0)
④若|x1-x0|<=eps,则停止迭代,输出x1
⑤若迭代次数超过m,则方法失败;否则x0=x1转3
4.代码
// 不动点迭代法
double FixedPointIteration(double f(double x), double x0, double eps,int *m)
{
double x1;
double d = 0;
do
{
x1 = f(x0);
d = x1 - x0;
x0 = x1;
(*m)--;
} while (fabs(d) >= eps); // 在精度范围内迭代,防止溢出
return x1;
}
5.优缺点
优点:运算简单,易于实现。若迭代公式收敛,只要迭代次数足够,可使结果达到指定精度
缺点:需选取合适的迭代次数
(四)牛顿迭代法
1.基本思想及介绍
Newton迭代法的优点在于,在单根附近具有平方收敛,而且可以求重根、复根。基本思想是将非线性方程转换为线性方程,又因为这是根据导数进行计算,又被称为切线法。
2.步骤
3.代码
// 牛顿迭代法
double NewtonRaphson(double f(double x), double df(double), double x0, double eps,int *m)
{
double x2;
x2 = x0 - f(x0) / df(x0);
do
{
x0 = x2;
x2 = x0 - f(x0) / df(x0); // 收敛性迭代计算
} while (fabs(x2 - x0) >= eps&&*m);
return x2;
}
4.优缺点
由Newton迭代法构造过程可知,初始值x0须足够靠近x*才能保证迭代函数的导函数变化不大,此时用 f‘作为其近似才会有较好的收敛性。如果初始值远离 x*迭代过程未必收敛。所以Newton迭代通常与其它算法配合使用。比如在找到有根区间后,用二分法求到一个相当接近于 x*的近似根作为 x0再启动Newton迭代过程,以达到加速收敛的效果.
优点:具有二阶收敛速度
缺点:对初值非常敏感、需要求导数
(五)弦截法
1.定义
弦截法是以与曲线弧AB对应的弦AB与x轴的交点横坐标作为曲线弧AB与x轴的交点横坐标的近似值μ来求出方程的近似解。该方法一般通过计算机编程来实现。弦截法的原理是以直代曲即用弦(直线)代替曲线求方程的近似解,也就是利用对应的弦 与 轴的交点横坐标来作为曲线弧 与 轴的交点横坐标 的近似值。
2.原理
方程实数解的几何意义是曲线与x轴交点的横坐标。弦截法的原理是以直代曲即用弦(直线)代替曲线求方程的近似解,也就是利用对应的弦AB与x轴的交点横坐标来作为曲线弧AB与x轴的交点横坐轴的近似值。
3.步骤
4.代码
//弦截法
double Secant(double f(double x), double x0, double x1, double eps,int *m)
{
double x2;
x2 = x0 - f(x0) * (x0 - x1) / (f(x0) - f(x1));// 获取与参数x,x1相对应的函数值
do
{
x1 = x0;
x0 = x2;
x2 = x0 - f(x0) * (x0 - x1) / (f(x0) - f(x1));
} while (fabs(x2 - x0) >= eps&&*m);
return x2;
}
5.优缺点
优点:不需要求导数噢~
缺点:对初值非常敏感,而且比牛顿法收敛慢
(六)黄金值分割法
1.基本思想
黄金分割法是建立再区间消去法原理基础上的试探方法,即在搜索区间[a,b]内适当插入两点c、d,并计算其函数值。c、d将区间分成三段,通过比较函数值大小,删去其中一段,使得搜索区间得以缩小。然后在保留下的区间上作同样的操作。这样子迭代下去,搜索区间逐渐缩小,当满足预先给定的精度时,即获得所求。
2.步骤
①给定区间[a,b]及误差eps;
②计算c=a+0.382(b-a), d=a+0.618(b-a);
③若f(c)>f(d)转④否则转⑤;
④若d-c<eps ,则转⑥,否则a=c, c=d, d=a+0.618(b-a),转③;
⑤若d-c<eps ,则转⑥,否则b=d, d=c, c=a+0.382(b-a),转③。
⑥若f(c)<f(d)输出c,否则输出d
3.代码:
// 黄金值搜索法
double GoldenSection(double f(double x), double a, double b, double eps,int *m)
{
double fc, fd, c, d;
c = a + 0.382 * (b - a);
d = a + 0.618 * (b - a);
fc = (*f)(c);
fd = (*f)(d);
while (d - c >= eps && *m)//在精度范围内进行计算,以防止溢出
{
if (fc > fd)
{
a = c;
c = d;
d = a + 0.618 * (b - a);
}
else
{
b = d;
d = c;
c = c = a + 0.382 * (b - a);
}
fc = (*f)(c);
fd = (*f)(d);
(*m)--;
}
return fc < fd ? c : d;//Return gold value
}
4.评价
黄金值搜索的方法仅需要计算函数值, 适用范围广, 使用方便。好耶ヽ(✿゚▽゚)ノ!
三、实验结果
如图所示啦~
那么,就到此为止吧,再写,就不礼貌了(bushi)
四、实验感悟
解决一个问题的方法有很多,基本的思想也有互通之处,在求解问题的过程中成功完成了实验,虽然略显粗糙,但是也加深了我对数值分析的理解,还有使用指向函数的指针的能力(hhhh)。最后一次数值计算实验报告啦,感谢!