牛顿迭代法

求二次根

各位同学可能遇到过这样的编程题目,要求在不使用的前提下,求解的正二次根。
可以用牛顿迭代法解:

    def mysqrt(c, x = 1, maxiter = 10, prt_step = False):
        for i in range(maxiter):
            x = 0.5*(x+ c/x)
            if prt_step == True:
                # 在输出时,{0}和{1}将被i+1和x所替代
                print "After {0} iteration, the root value is updated to {1}".format(i+1,x)
        return x

    print mysqrt(2,maxiter =4,prt_step = True)
    # After 1 iteration, the root value is updated to 1.5
    # After 2 iteration, the root value is updated to 1.41666666667
    # After 3 iteration, the root value is updated to 1.41421568627
    # After 4 iteration, the root value is updated to 1.41421356237
    # result : 1.4142135623746899

牛顿迭代法(Newton's Itervative Method)

上面的求正二次根问题,等价于求的正根 根据上一节介绍的线性近似:
如果的一个根,即,则:

因此,如果我们对的正根有一个初始估计,便可以用上面的近似不断获取更加准确的估计值,方法为:

带入上式,便会得到代码中的跟新规则了。

通过绘图我们能进一步了解这个方法(喜闻乐见的绘图时刻又到了!):

    f = lambda x: x**2-2*x-4
    l1 = lambda x: 2*x-8
    l2 = lambda x: 6*x-20

    x = np.linspace(0,5,100)

    plt.plot(x,f(x),'black')
    plt.plot(x[30:80],l1(x[30:80]),'blue', linestyle = '--')
    plt.plot(x[66:],l2(x[66:]),'blue', linestyle = '--')

    l = plt.axhline(y=0,xmin=0,xmax=1,color = 'black')
    l = plt.axvline(x=2,ymin=2.0/18,ymax=6.0/18, linestyle = '--')
    l = plt.axvline(x=4,ymin=6.0/18,ymax=10.0/18, linestyle = '--')

    plt.text(1.9,0.5,r"$x_0$", fontsize = 18)
    plt.text(3.9,-1.5,r"$x_1$", fontsize = 18)
    plt.text(3.1,1.3,r"$x_2$", fontsize = 18)


    plt.plot(2,0,marker = 'o', color = 'r' )
    plt.plot(2,-4,marker = 'o', color = 'r' )
    plt.plot(4,0,marker = 'o', color = 'r' )
    plt.plot(4,4,marker = 'o', color = 'r' )
    plt.plot(10.0/3,0,marker = 'o', color = 'r' )

    plt.show()

08-01NewMeth

我们要猜的解,从的初始猜测值开始,找到处的切线,找到其与的交点,将该交点更新为新的猜测的解,如此循环。

如下定义牛顿迭代法:

    def NewTon(f, s = 1, maxiter = 100, prt_step = False):
        for i in range(maxiter):
            # 相较于f.evalf(subs={x:s}),subs()是更好的将值带入并计算的方法。
            s = s - f.subs(x,s)/f.diff().subs(x,s)
            if prt_step == True:
                print "After {0} iteration, the solution is updated to {1}".format(i+1,s)
        return s

    from sympy.abc import x
    f = x**2-2*x-4
    print NewTon(f, s = 2, maxiter = 4, prt_step = True)
    # After 1 iteration, the solution is updated to 4
    # After 2 iteration, the solution is updated to 10/3
    # After 3 iteration, the solution is updated to 68/21
    # After 4 iteration, the solution is updated to 3194/987
    # 3194/987

Sympy可以帮助我们求解方程,不要教坏小朋友们哦:

    sympy.solve(f,x)
    # result: [1 + sqrt(5), -sqrt(5) + 1]

results matching ""

    No results matching ""