对分法求非线性方程的根

来源:互联网 发布:手机推广软件 编辑:程序博客网 时间:2024/05/01 19:38

对于非线性方程的求解,有时候很难找到解的解析函数,所以只能才用数值求解。常见的一些非线性方程为这里写图片描述

算法的基本原理:如果非线性方程f(x)=0,的左端函数f(x)在区间[a,b]上连续,并满足f(a)f(b)<0,则方程至少有一个实根。
基本思想:逐步缩小这个有根的区间,当这个区间减少到一定程序时,就取这个中点作为根的近似值。

如果在区间[a,b]内有多个实根,则单独利用对分法只能得到其一个实根。所以,将对分法与逐步扫描法结合使用,以便尽量搜索给定区间的实根,这种方法概括如下:
(1)从区间左端点x=a开始,以h为步长,逐步往后进行搜索。
(2)对于在搜索过程中遇到的每一个子区间[xk,xk+1], 其中,xk+1=xk+h。进行如下处理:
1.若f(xk)=0,则xk为一个实根,从xk+0.5h开始往后搜索
2.容易f(xk+1)=0,则xk+1为一个实根,从xk+1+0.5h开始搜索
3.若f(xk)f(xk+1)>0,则子区间无实根或h选的过大,放弃本子区间,从xk+1开始搜索
4.容易f(xk)f(xk+1)<0,则当前区间有实根,继续利用对分法,直到求到一个实根为止。,然后从
xk+1开始往后搜索。

代码如下:

/*二分法搜索方程的实根*函数int dhrt(double a,double b,double h,double eps,double *x,int m,double (*f)(double))*double a:求根区间的左端点*double b:求根区间的右端点*double h:搜索求根时所采用的步长*double eps:控制的精度要求*double* x:返回在区间[a,b]搜索到的实根。实根个数由函数值返回*int m:在区间[a,b]内实根个数的预估值*double  (*f)(double):f(x)的迭代函数*/#include <iostream>#include<cmath>#include<iomanip>using namespace std;int dhrt(double a, double b, double h, double  eps, double *x, int m, double(*f)(double)){    int n = 0;    int js = 0;    double z = a;                                //搜素区间的中间点    double z1;                                  //定义的搜素区间的末端    double z0;                                   //定义的搜素区间的起始端    double y1;                                    //用于存放z1点的函数结果    double y0;                                   //用于存放z0点的函数结果    double y = (*f)(z);                           //用于存放函数z点处的函数结果                                                  //计算过程    while ((z <= b + h / 2) && (n != m))    {        if (fabs(y)<eps)                        //如果值满足“精度要求eps“下的0状态        {            n = n + 1;                             //进行下一次查找            x[n - 1] = z;                          //保存节点值            z = z + h / 2.0;                         //变换起始区间加0.5h继续搜素            y = (*f)(z);                         //计算中点处的值        }        else                                    //当中点处的值不满足精度要求的根时        {            z1 = z + h;                             //z1是搜素的子尾区间点            y1 = (*f)(z1);                        //计算子尾点区间的值            if (fabs(y1)<eps)                      //如果子尾区间点的值正好满足精度要求            {                n = n + 1;                             //则同上,保存根                x[n - 1] = z;                z = z1 + h / 2.0;                          //子区间起始点加0.5h                y = (*f)(z);            }            else if (y*y1>0.0)                        //首尾根节点的函数值为正,则表示无根,所以往后开始搜素            {                y = y1;                z = z1;            }            else                                       //如果有根,则二分查找            {                js = 0;                while (js == 0)                             //立一个flag                {                    if (fabs(z1 - z)<eps)                    //如果(z1-z)满足精度要求                    {                        n = n + 1;                        x[n - 1] = (z1 + z) / 2.0;                        z = z1 + h / 2.0;                           //搜素起始区间加h                        y = (*f)(z);                        js = 1;                               //flag为1                    }                    else                                   //如果不满足判断要求,继续二分                    {                        z0 = (z1 + z) / 2.0;                      //计算中点处的值                        y0 = (*f)(z0);                        if (fabs(y0)<eps)                    //满足精度要求就保存,同上                        {                            x[n] = z0;                            n = n + 1;                            js = 1;                            z = z0 + h / 2;                            y = (*f)(z);                        }                        else if (y*y0<0.0)                      //相异有根                        {                            z1 = z0;                            y1 = y0;                        }                        else                                //否则相同无根                        {                            z = z0;                            y = y0;                        }                    }                }            }        }    }    return n;}double func(double x){    return x*x - 3 * x + 2 - exp(x);}int main(){    cout << "Hello world!" << endl;    double a[5];    int n;    n = dhrt(0, 1, 0.05, 0.0000001, a, 2, func);    cout << n << endl;    cout << setprecision(8) << a[0] << "   " << endl;    return 0;}

注意一点:函数指针那个子程序是对应着不同的函数,需要自己定制!!

1 0
原创粉丝点击