牛顿迭代法(Newton's Method)

原创 2016年08月31日 15:17:40

 牛顿法的作用是使用迭代的方法来求解函数方程的根。简单地说,牛顿法就是不断求取切线的过程。


对于形如f(x)=0的方程,首先任意估算一个解x0,再把该估计值代入原方程中。由于一般不会正好选择到正确的解,所以有f(x)=a。这时计算函数在x0处的斜率,和这条斜率与x轴的交点x1。

f(x)=0中精确解的意义是,当取得解的时候,函数值为零(即f(x)的精确解是函数的零点)。因此,x1比x0更加接近精确的解。只要不断以此方法更新x,就可以取得无限接近的精确的解。

但是,有可能会遇到牛顿迭代法无法收敛的情况。比如函数有多个零点,或者函数不连续的时候。


牛顿法举例


下面介绍使用牛顿迭代法求方根的例子。牛顿迭代法是已知的实现求方根最快的方法之一,只需要迭代几次后就能得到相当精确的结果。

首先设x的m次方根为a。


下面程序使用牛顿法求解平方根。 

 <pre name="code" class="java">package com.apple.other;
/**
 * 开方,牛顿迭代法
 */
public class Sqrt {

    private static double E = 0.0000001d;
    
    /**
     * 开平方
     * @param x
     * @return
     */
    public static double sqrt(int x){
        double result = x;
        while(Math.abs(result * result - x) > E){
            result = (result + x/result) / 2;
        } 

        return result;
    }

    /**
     * 开n次方
     * @param x
     * @param n
     * @return
     */
    public static double sqrtN(int x, int n){
        double result = x;
        while(Math.abs(Math.pow(result, n) - x) > E){
            result = ((n - 1) * result + x/Math.pow(result, n - 1) ) / n;
        } 

        return result;
    }

    public static void main(String[] args) {
        System.out.println(Sqrt.sqrt(8));
        System.out.println(Sqrt.sqrtN(27, 3));
    }

}



更快的方法


文献2提到了比上述程序更快的求解平方根的非典型牛顿迭代法。介绍如下。

1999年12月,美国id Software公司发布了名为“雷神之锤III”的电子游戏。它是第一个支持软件加速的游戏,取得了极大成功。(由于影响力过大,文化部于2004年将它列入了非法游戏名单)

雷神之锤III并不是id Software公司的第一次成功。早在1993年开始,这家公司就以“毁灭战士”系列游戏名闻天下。1995年,“毁灭战士”的安装数超过了当年微软的windows 95。据传比尔盖茨才曾经考虑买下id software。(id software公司后来被推出过“上古卷轴”系列的Bethesda公司买下)

id Software所取得的成功很大程度上要归功于它的创始人约翰·卡马克。马克尔也是一个著名的程序员,他是id Software游戏引擎的主要负责人。 回到刚才提到的雷神之锤,马克尔是开源软件的积极推动者,他于2005年公布了雷神之锤III的源代码。至此人们得以通过研究这款游戏引擎的源文件来查看它成功的秘密。

在其中一个名字为q_math.c的文件中发现了如下代码段。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. float Q_rsqrt( float number ) {   
  2.     long i; float x2, y; const float threehalfs = 1.5F;  
  3.     x2 = number * 0.5F;   
  4.     y = number;   
  5.     i = * ( long * ) &y; // evil floating point bit level hacking   
  6.     i = 0x5f3759df - ( i >> 1 ); // what the fuck?   
  7.     y = * ( float * ) &i;   
  8.     y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration   
  9.     // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed  
  10.     #ifndef Q3_VM #  
  11.     ifdef __linux__ assert( !isnan(y) ); // bk010122 - FPE?  
  12.     #endif  
  13.     #endif return y;   
  14. }  

这段代码的作用就是求number的平方根,并且返回它的倒数。

经过测试,它的效率比上述牛顿法程序要快几十倍。也比c++标准库的sqrt()函数要快好几倍。此段代码有一个奇怪的句子:

i = 0x5f3759df - ( i >> 1 ); // what the fuck? 

这句话的注释是“what the fuck?”,翻译过来就是“我靠?”

任何受过程序训练的人看到这句大概都会在想,这句话到底在搞什么鸟?

之所以会出现这种奇怪的注释,要么是此段程序的作者(可能是马克尔)根本不知道该如何解释清楚,或者是维护这段程序的程序员完全看不懂这句话,所以有点儿抓毛。而实际上,它的作用(再加上y = y * ( threehalfs - ( x2 * y * y ) )这句牛顿迭代)就是求平方根。

至于是为什么,本博主也不知道。

以雷神之锤III程序为蓝本可以写出比sqrt()更强大的求平方根函数:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int sqrt(float x) {   
  2.     if(x == 0) return 0;   
  3.     float result = x;   
  4.     float xhalf = 0.5f*result;   
  5.     int i = *(int*)&result;   
  6.     i = 0x5f375a86- (i>>1); // what the fuck?   
  7.     result = *(float*)&i;   
  8.     result = result*(1.5f-xhalf*result*result); // Newton step, repeating increases accuracy   
  9.     result = result*(1.5f-xhalf*result*result);   
  10.     return 1.0f/result;   
  11. }  


参考文献:
1.wikipedia.org
2.http://www.2cto.com/kf/201206/137256.html


版权声明:欢迎转载,请注明出处:http://blog.csdn.net/bluetjs

牛顿迭代法 简单入门

引言牛顿迭代法是在计算机编程领域广泛用来求解方程的算法。此算法类似于二分枚举(仅仅感觉上很类似= =) 我们每次枚举一个值X0X_0,代入方程看是否为根,不是的话则将X0X_0的值变为: X0=X...

牛顿迭代法

牛顿迭代 详细介绍见维基百科 http://zh.wikipedia.org/wiki/牛顿法   举一个栗子 找平方根 给一个数a,求其平方根。   设其平方根为x 则有 x^2 - a...
  • yew1eb
  • yew1eb
  • 2014年08月21日 13:11
  • 2301

牛顿迭代法(Newton's Method)

牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出。但是,这一方法在牛顿生前并未公开发表。 牛顿法的作用是使用迭代的方法来求解函数方程的根。简单地说,牛顿法就是不断求取切线的过程。 对于形...

牛顿迭代法(Newton's Method)

牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出。但是,这 一方法在牛顿生前并未公开发表(讨厌的数学家们还是鼓捣出来了) 牛顿法的作用是使用迭代的方法来求解函数方程的根。简单地说...

牛顿迭代式(Newton's Method)解多次方程

设r是 的根,选取 作为r的初始近似值,过点 做曲线 的切线L,L的方程为 ,求出L与x轴交点的横坐标 ,称x1为r的一次近似值。过点 做曲线 的切线,并求该切线与x轴交点的横坐标 ...
  • lmhacm
  • lmhacm
  • 2017年05月01日 19:45
  • 936

再谈 牛顿法/Newton's Method In Optimization

转自:http://www.codelast.com/?p=8052 牛顿法是最优化领域的经典算法,它在寻优的过程中,使用了目标函数的二阶导数信息,具体说来就是:用迭代点的梯度和二阶导数对目...

基础牛顿法及其变形(basic Newton's method & its variants)

本篇详细介绍牛顿法及其各种形式的变形,并给出收敛性质。 1. 经典牛顿法二阶收敛 2. 中点牛顿法(MN)三阶收敛,通常具有最好的性质 3. 算术平局值牛顿法(AN)、调和平均数牛顿法(HN)、反调和...

牛顿迭代法(牛顿-拉弗森方法(Newton-Raphson method))

起源[编辑] 牛顿法最初由艾萨克·牛顿在《流数法》(Method of Fluxions,1671年完成,在牛顿死后的1736年公开发表)。约瑟夫·拉弗森也曾于1690年在Analysis ...
  • szlcw1
  • szlcw1
  • 2014年04月22日 21:22
  • 6333

最大化对数似然函数——牛顿方法(The Newton's method)

描述一种相比梯度下降更快的迭代收敛算法——牛顿方法

用matlab实现牛顿迭代法

  • 2012年10月28日 21:13
  • 154B
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:牛顿迭代法(Newton's Method)
举报原因:
原因补充:

(最多只允许输入30个字)