Sqrt函數(shù)可視化實(shí)現(xiàn)

練習(xí):Sqrt函數(shù)可視化實(shí)現(xiàn)

本次練習(xí)主要是熟練numpy和matplotlib的使用,通過手寫Sqrt的實(shí)現(xiàn),通過可視化對(duì)比手寫函數(shù)與系統(tǒng)自帶函數(shù)之間區(qū)別。

主要實(shí)現(xiàn)思路是:牛頓法

下面簡單介紹一下牛頓法:(參考博客參考知乎) 首先,有函數(shù)f(x) = x2,假設(shè)num是f(x)的近似值,那么num最接近f(x),就有f(x)-num=0,也就是x2 - num = 0.

那么如果畫圖,就是要求g(x)=x2 - num 與g(x)=0 的最近點(diǎn)。

極限公式:

因此有:

從幾何圖形上看,因?yàn)閷?dǎo)數(shù)是切線,通過不斷迭代,導(dǎo)數(shù)與x軸的交點(diǎn)會(huì)不斷逼近x0。

從上圖我們可以看出,第一次A點(diǎn),畫出A的切線,在X軸上有交點(diǎn),這個(gè)交點(diǎn)投影到曲線上,找到點(diǎn)B,同理,B點(diǎn)又做切線,找到一個(gè)交點(diǎn),交點(diǎn)又投影到曲線得到點(diǎn)C,逐漸接近X0。

由前面的極限公式得出:

$$f'(x_n) = \frac{dy}{dx} = \frac{f(x_n)}{x_n - x_{n+1}}$$

推導(dǎo)得出:

$$x_{n+1} = x_n -\frac{f(x_n)}{f'(x_n)}$$

ok,到這里我們舉一個(gè)實(shí)例

假設(shè)m=2,那么就有:

最終得出以下圖例:手寫的sqrt函數(shù)與系統(tǒng)自帶的基本沒有區(qū)別

# -*- coding:utf-8 -*-
# /usr/bin/python

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import math


def func(a):
    if a < 1e-6: #小于0.000001,直接返回0
        return 0
    last = a
    c = a / 2     #該值一定程度上影響迭代次數(shù)
    while math.fabs(c - last) > 1e-6:#精度控制
        last = c
        c = (c + a/c) / 2
    return c


if __name__ == '__main__':
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False #保證win系統(tǒng)圖片上的中文顯示正常
    x = np.linspace(0, 30, num=50)  #0-30均分50份
    func_ = np.frompyfunc(func, 1, 1) #轉(zhuǎn)換為ufunc函數(shù)方便使用
    y_h = func_(x)
    y_s = np.sqrt(x)#調(diào)用系統(tǒng)自帶函數(shù)求值
    plt.figure(figsize=(10, 6), facecolor='w')#設(shè)置圖大小和背景色
    plt.plot(x,y_h, 'ro-',label='手寫', lw=2, markersize=6)#(畫出x與y_h的曲線,用紅色小圓圈標(biāo)記(x,y)在圖上的位置,
    #label下面legend函數(shù)要調(diào)用的,相當(dāng)于注明這條曲線的意義,lw線寬2,小圓點(diǎn)6)
    plt.plot(x,y_s, 'b-',label='系統(tǒng)自帶', lw=2, markersize=6)
    plt.grid(b=True, ls=':')#顯示網(wǎng)格
    plt.legend(loc='lower right')#選取兩條曲線的注明所在方位
    plt.xlabel('X', fontsize=16)#坐標(biāo)軸上的內(nèi)容及大小
    plt.ylabel('Y', fontsize=16)
    plt.title('牛頓法計(jì)算平方根', fontsize=18)
    plt.show()

關(guān)于分母的取值影響迭代次數(shù)的研究

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import math


def func(b):
    if b < 1e-6:
        return 0
    a = 1000
    last = a
    c = a / b
    count = 0
    while math.fabs(c - last) > 1e-6:
        last = c
        c = (c + a/c) / 2
        count = count + 1
    return count


if __name__ == '__main__':
    x = np.linspace(2, 500, num=100)
    func_ = np.frompyfunc(func, 1, 1)
    y = func_(x)
    print(x,y)
    
>>>[9 7 6 5 5 4 3 4 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7
 7 7 7 7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 9 9 9 9 9 9 9 9 9]

這里我們假定對(duì)1000開方,取出2-500之間的100個(gè)數(shù),得到的結(jié)果是卻是迭代次數(shù)從9最低降到3又升到9。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容