非线性方程求解:孙悟空与贾宝玉的前世今生

1.此系身前身后事,倩谁记去作奇传

空空道人访道求仙,偶遇巨石,有诗偈云:“无才可去补苍天,往如红尘若许年。此系身前身后事,倩谁记去作奇传。”  原为女娲补天的灵石,不知过了几世几劫,幻形入世被那蒙茫茫大仙、渺渺真人携入红尘,历尽悲欢离合炎凉事态......——《红楼梦》第一回 甄士隐梦幻识通灵 贾雨村风尘怀闺秀

“傲来国内有一仙石,自开天辟地以来,每受天真地秀,日精月华,感之既久,遂有灵通之意......”——《西游记》第一回 灵根育孕源流出 心性修持大道生

两部巨著的第一回均介绍了主角的身世,巧合的是不管是贾宝玉还是孙悟空——都是由石头幻化入形,生灵通意。那孙悟空和贾宝玉到底有什么关系?吴承恩和曹雪芹两位大师为什么会一致性的偏爱石头?......值得考究,不过这篇文章的重点并不在此,只是借此引入本篇的主题:非线性方程的求解问题。本篇主要介绍牛顿法和弦截法,两者的共同点都是利用计算机强大的计算能力弥补人类智力在量化累计面前的短板,就如同孙悟空和贾宝玉的身世都可以追溯到石头一样,本质并没有太大区别,而两种方法所用的迭代/循环求解的过程 就如灵石历经轮回幻化成形的过程,量化堆积,以求质变。说到这里悟空和宝玉的身世疑团逐渐揭开,欲知后事如何,且听下回分解。

2.牛顿迭代法-定海神珍铁

将方程转化为函数,再根据函数图像性质及导函数的性质求解的过程,是一个由数到图的过程,我们对于图像的感知认识比单纯的数据更为敏感,这使方程的求解问题感性化,以此简化问题。对于牛顿迭代的原理这里不做过多文字性的论述,如下图:


牛顿迭代法所要考虑的问题主要有三点:确定迭代变量;建立迭代关系式;对迭代过程进行控制。

1).迭代变量 => 自变量x;

2).迭代关系 => 牛顿迭代关系式;

3).控制条件 => 取决于问题所要求解的精度(x1-x2);

可以看到迭代的次数越多就越接近图像与横坐标的交点,f(x)的值就如同如意金箍棒一样逐渐缩小,直到趋于0时,此时的x即为所求方程的根。纸上得来终觉浅,觉知此时要躬行(c语言版):


void NewtonIter(float a){
    float x2 = a,x1;
    float f1, f2;

    do{
        x1 = x2;
        //函数关系式(例)
        f1 = ((2*x1 - 4)*x1 + 3)*x1 - 6;
        //导函数
        f2 = (6*x1 - 8)*x1 + 3;
        x2 = -f1/f2 + x1;
    }while(fabsf(x2-x1) >= 1e-5);
    printf("The root of equation is %5.2f\n",x2);
}

ps:东海那么大的水都能给定住,何况一个区区的x!

3.弦截法-宝玉入世

“数缺形时少直观,形少数时难入微,数形结合百般好,隔离分家万事休。”-看图说话:


弦截法实质上也是一种以直代曲的迭代方法,不同的是它得确定一个有值区间,通过不断缩小区间进行求解,既然是迭代法,那我们首先要考虑三个关键的问题:

1).迭代变量 => 自变量x;

2).迭代关系 => 通过区间端点确定弦与横坐标交点的关系式;

3).控制条件 => 取决于问题所要求解的精度(f(x)趋于0的进度);

在迭代过程中通过连续函数介值定理确定零点区间,知道f(x)的大小满足所规定的精度要求时,此时的x即为方程的根。又到了行胜于言的时候后了,上码:

#include<stdio.h>
#include<math.h>

float f(float x);
float xpoint(float a, float b);
float root(float a, float b);

int main(){
    float a, b, x,f1,f2;
    //输入区间
    do{
        printf("input a b : \n");
        scanf("%f%f",&a,&b);
        f1 = f(a);
        f2 = f(b);
    }while (f1*f2 > 0);
    
    x = root(a,b);
    
    printf("a root of equation is : %8.4f\n", x);
    
    return 0;
}

float f(float x){
    float y;
    y = ((x-5.0)*x + 16.0)*x - 80.0;
    return y;
}

float xpoint(float a, float b){
    float x;
    x = (a*f(b) - b*f(a))/(f(b) - f(a));
    return x;
}

float root(float a, float b){
    float x;
    do{
        //根据输入区间计算弦零点
        x = xpoint(a,b);
        //确定下一次的迭代区间
        if(f(a)*f(x) < 0){
            b = x;
        }else{
            a = x;
        }
        //判断f(x)是否终止迭代
    }while(fabsf(f(x)) >= 1e-4);
    return x;
}

ps:二分法比较相似,只是该方法是用弦来确定分割点。可以看出该过程是弦逐渐在缩短,寻找最终的“落脚点”,当达到所求零点的精度要求,玉入凡尘,方程得解。

4.严肃分析,各有千秋

1)牛顿迭代法本身有其不可替代的优越性:它只需要在根附近随便找一数作为基点便可迭代求解,事实上该基点的指定可以很随意。但是这并不能掩盖它自身的缺陷:需要导函数的存在,而且导函数为0的值若在基点与解之间则可能会出现无法求解的尴尬状况,虽然这种情况的出现概率极低,失之毫厘谬以千里,还是得足够重视。

2)弦截迭代法相比于牛顿法优势则显得十分明显:首先它不需要关注导函数的状况,其次该方法使用区间“卡”值,因此求解速度略胜一筹。人无完人:这种方法的区间求解的方法没有牛顿法那么随意,使用之前得确定零点区间。

3)没有完美的法则,两种方法各有千秋,在实际问题中可以搭配使用,互为补充。这一篇章没有介绍什么有意思的算法,只觉得非线性方程求解在实际工程中十分常见,所以写一下最近接触的两个方法,当然后面若遇到其他的方法会进行扩展补充。关于孙悟空和贾宝玉的身世问题自己也十分纠结:反正两个人都是石头,一个是做石头做的太久,所以对自由的追求太过痴狂,当然也为此在五行山下被其他石头镇了五百年;另一个则风花雪月,痛恨八股,批程朱理学... ... 其实这些行为也可以看做是一种挣脱束缚的表现,那最后出世为僧,是落个自在还是被迫无奈...... 最后发现还是做石头更加淡定,至少可以为地质勘探员提供一些寻找能源矿产的方向。


4)声明:关于《西游记》和《红楼梦》部分情节纯属虚构不必较真。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值