非线性方程求根(数值分析)C++

1. 二分搜索

  经典算法了,数组的二分检索和它相似,不过数组的二分查找要求数组有序,反映在非线性方程求根就是函数单调。不过二分搜索不要求函数单调。因为随着区间长度减半,如果能够求出满足精度的近似解,不断减半的区间内,函数终会单调。

  需要注意的还有:如果循环结束条件为所求近似根满足精度,如果搜索区间内没有根,那么很有可能无法结束循环,并且设计逻辑比较复杂,根据区间长度是否小于一定长度决定是否结束循环比较合理。

  params: 区间端点,要求的精度

  return: 近似解

自己定义一个函数,例如:double fun1(double x) {return x * x * x - x - 1;}

int iterCount = 0;
double binarySearch(double left, double right, double precision) {
    double mid = (left + right) / 2;
    iterCount++;
    printf("\n二分迭代次数为: %d\n", iterCount);
    double result = fun1(mid);
    if (right-left < precision) {
        return mid;
    }
    else if (result * fun1(left) < 0) {
        return binarySearch(left, mid, precision);
    }
    else if (result * fun1(right) < 0) {
        return binarySearch(mid, right, precision);
    }
    else {
        return binarySearch(mid, right, precision);
    }
    return 0;
}

2. 简单迭代法

  通过移项,使方程等号左侧为x。需要注意的是,迭代方程要保证收敛,如何移项就是考技巧了。需要注意的是,迭代法不需要指定区间,它是自适应的搜索。不过需要指定初始解,这也是启发式算法的特征。

  以下大体框架也适用于牛顿迭代法,割线迭代法。程序稍加修改就成了。

  params: 初始解,要求的精度

  return: 近似解

自己定义一个迭代函数,比如:double fun2(double){ return 0.25*(x * x * x * x * x - 2);}

double simpleIterator(double x0, double err) {
    double f0 = fun2(x0);
    double f1 = fun2(f0);
    double res = f1 - f0;
    iterCount++;
    if (res < 0) {
        res = -res;
    }
    while (true) {
        f0 = f1;
        f1 = fun2(f0);
        double res = f1 - f0;
        if (res < 0) {
            res = -res;
        }
        if (res < err)
            break;
    }
    return f1;
}

 

上一篇:ECR102E(求减掉最长边加上最短边的最短路)


下一篇:Cisco(思科)路由器端口的配置