寻找“最好”(8)——牛顿法

  牛顿是近代科学的先驱,智商290,碾压无数学霸,一个苹果都能砸出万有引力定律。

  在力学上,牛顿阐明了动量和角动量守恒的原理,提出牛顿三大运动定律,它们和万有引力定律奠定了此后三个世纪里物理世界的科学观点,并成为无数中学生的噩梦。牛顿他通过论证开普勒行星运动定律与他的引力理论间的一致性,展示了地面物体与天体的运动都遵循着相同的自然定律;为太阳中心说提供了强有力的理论支持,并推动了科学革命。

  在天文学上,牛顿创制了反射望远镜。他还用万有引力原理说明潮汐的各种现象,指出潮汐的大小不但同月球的位相有关,而且同太阳的方位有关。牛顿预言地球不是正球体。

  在哲学上,牛顿的哲学思想基本属于自发的唯物主义,他承认时间、空间的客观存在。如同历史上一切伟大人物一样,牛顿虽然对人类作出了巨大的贡献,但他也不能不受时代的限制。例如,他把时间、空间看作是同运动着的物质相脱离的东西,提出了所谓绝对时间和绝对空间的概念;他对那些暂时无法解释的自然现象归结为上帝的安排,提出一切行星都是在某种外来的“第一推动力”作用下才开始运动的说法。

  在经济学上,牛顿提出金本位制度。这是一种以黄金为本位币的货币制度,当不同国家使用金本位时,国家之间的汇率由它们各自货币的含金量之比——金平价来决定。

  在数学上,我们已经见识过牛顿的微积分,他与莱布尼茨共同分享了微积分学的荣誉,尽管哥俩为谁的功劳大掐过架。

  此外,牛顿还提出了著名的牛顿法(Newton's method)也叫牛顿迭代法,它是牛顿在17世纪提出的一种在实数域和复数域上近似求解值的方法。

牛顿法

  先来看如何用牛顿迭代法求解5的平方根。

  首先令f(x)= x2 – 5,这是标准步骤,取得一个新函数;再令该函数为0,这样原问题就可以看作是解方程x2 – 5 = 0。f(x)是一个抛物线:

  抛物线与x轴正方向的交点x就是方程的解,它比2稍大一点。

  现在在x = 2的点(2, -1)处对f(x)做切线,切线方程是y = kx + b,斜率k是f(x)在x = 2处的导数:

  将(2, -1)代入切线后得到截距b= -9:

 

  设f(x)与x轴正半轴的交点是x,切点是x0,切线与x轴的交点是x1,x1在x的右侧:

  由于x1贴近x,所以只要求得x1就能近似地求出x。求解x1的方法之一是找出过x0的切线,之后计算切线与x轴的交点。设切线的斜率是k,根据斜率的公式:

  过x0的切线的斜率正式f(x)在x0处导数的定义,因此:

  这样一来就找到了x的近似解x1。然而x1还没达到标准,我们还想更贴近真实值一点,这次选取更进接近x的(x1, f(x1))做切点,新切点的切线与x轴的交点x2将比原来的x1更贴近x:

  计算器上计算根号5的结果是2.236067,x2的值已经相当接近。

  重复上面步骤,每一次迭代的结果都将更接近真实值:

  这就是牛顿迭代法的公式。

牛顿法的注意事项

  牛顿迭代法几乎可以求解所有方程,但它仍然有一些限制。

  在使用牛顿迭代法时,需要选取x0作为迭代基数,x0如何选取呢?一句参考是:x0要在x附近,它是一个较为解接近真实解的值,这要凭经验和感觉了,没有什么太好的办法。

  实际上,如果x0和x的差距过大,可能会得到一个没谱的解。以计算5的平方根为例,如果选择x0= -2,结果将偏向于-2.236067;如果选择x0=0,则f’(0)=0,没法继续迭代:

  设第n次迭代的误差是En=|x-xn|,那么需要满足En+1<En。如果选择和计算都正确,误差缩小的速度将非常快。

从泰勒公式看牛顿法

  泰勒展开式是一种计算近似值的方法,是一个用函数某点的信息描述在该点附近取值的公式,这就与牛顿法有些相似了。

  把f(x)在x0的某邻域内展开成泰勒级数:

  进一步得到:

  反复迭代就得到了牛顿法的公式:

解方程2cosx = 3x

  先作图,画出y = 2cosx和y = 3x的曲线:

  两条曲线相交于一点,方程存在唯一解。根据牛顿法,先设置f(x):

  两条曲线交点的位置似乎是π/6附近,所以选择π/6作为x0,根据牛顿迭代法:

  第二次迭代与第一次迭代的差距已经非常微小,可以说x2就是最终的近似解。

求平方根

  在一次code review会议上,一个同事展示了一段他不理解的C++代码:

 1 const float EPS = 0.00001;
 2 
 3 doublesqrt(doublex){
 4     if(x == 0)
 5         return 0;
 6 
 7     double result = x;
 8     double lastValue;
 9     do{
10         lastValue = result;
11         result = result/2.0f + x/2.0f/result;
12     }while(abs(result - lastValue) > EPS);
13 
14    return result;
15 }        

  sqrt函数是求平方根,并且运行的很好,虽然展示者能够看懂每一行代码,但不知道为什么要这么写,不明白那个神奇的2.0是什么意思。

  现在看起来,不懂数学都没法快乐地阅读代码了。这段代码其实是在使用牛顿法计算平方根,过程是这样的:

  如果改成计算机程序的写法:

  现在可以和第9行代码对应上了。

  


   作者:我是8位的

  出处:http://www.cnblogs.com/bigmonkey

  本文以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,非商业用途! 

  扫描二维码关注公众号“我是8位的”

posted on 2018-11-07 15:30  我是8位的  阅读(1944)  评论(0编辑  收藏  举报

导航