对分法求非线性方程的根

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

算法的基本原理:如果非线性方程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;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值