1. 程式人生 > >用Newton切線法、Newton下山法、割線法求一元非線性方程的近似解-Python

用Newton切線法、Newton下山法、割線法求一元非線性方程的近似解-Python

實驗內容

分別用Newton切線法、Newton下山法和割線法求方x22xex+2=0x^2-2x-e^x+2=0的近似根,其對應函式影象如下圖所示。
圖1  函式f(x) = x**2 - 2*x - exp(x) + 2 和函式f(x) = 0的影象

演算法描述

Newton切線法

迭代公式

xk+1=xkf(xk)f(xk)x_{k+1}=x_k-\frac{f(x_k)}{f (x_k)}

演算法流程圖

在這裡插入圖片描述

Newton下山法

xkx_kxk+1x_{k+1}之間找一個更好的點xk+1\overline{x_{k+1}}使得:f(xk+1)<f(xk)|f(\overline{x_{k+1}})|<|f(x_k)|

迭代公式

xk+1=xkrf(xk)f(xk)x_{k+1}=x_k-r\cdot\frac{f(x_k)}{f (x_k)}

演算法流程圖

在這裡插入圖片描述

割線法

迭代公式

xk+1=xkxkx0f(xk)f(x0)f(xk)x_{k+1}=x_k-\frac{x_k-x_0}{f(x_k )-f(x_0 ) } f(x_k )

演算法流程圖

在這裡插入圖片描述

實驗結果

在這裡插入圖片描述

Python程式碼求解

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/10/14 19:59 # @Author : Guojing Li # @File : SolveNonlinearEquation.py # @Software: PyCharm """ Methods of solving non-linear equation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This module includes three Methods of solving my non-linear equation and a plot function. You can choose a Methods to get the solution of my non-linear equation. This is my non-linear equation: x**2 - 2*x - exp(x) + 2 = 0 """
import math from matplotlib import pyplot as plt import numpy as np def plot_nonlinear_equation(): """ 繪製函式f(x) = x**2 - 2*x - exp(x) + 2 和函式f(x) = 0的影象 :return: None """ X = np.arange(-3, 3, 0.01) Y = [f(x) for x in X] plt.plot(X, Y, linewidth='2', linestyle="-" ) plt.hlines(0, -3, 3, colors='r') plt.xlim(-3, 3) plt.ylabel("f(x)") plt.xlabel("x") plt.legend(["f(x) = x**2 - 2*x - exp(x) + 2 ", "f(x) = 0"]) plt.show() def f(x): """ :param x: :return: f(x) """ return x**2 - 2*x - math.exp(x) + 2 def df(x): """ :param x: :return: f(x)的導數 """ return 2*x - 2 - math.exp(x) def tangent_method(x, ep=1e-05, max_iteration=500): """ 牛頓切線法求解非線性方程 :param x: x初始值 :param ep: 精度 :param max_iteration: 最大迭代次數 :return: 迭代次數, 方程的解 """ print("牛頓切線法求解方程,精度為", ep, ",最大迭代次數為", max_iteration) print("初始值:x =", x) for iteration in range(max_iteration): if (df(x) == 0): exit("導數為0,迭代失敗") x1 = x - f(x)/df(x) print("第", iteration+1, "次迭代,x =", x1) if(math.fabs(x1-x) <= ep): return iteration+1, x1 else: x = x1 exit("以迭代到上限值") def downhill_method(x, ep=1e-05, max_iteration=500): """ 牛頓下山法求解非線性方程 :param x: x初始值 :param ep: 精度 :param max_iteration: 最大迭代次數 :return: 迭代次數, 方程的解 """ print("牛頓下山法求解方程,精度為", ep, ",最大迭代次數為", max_iteration) print("初始值:x =", x) for iteration in range(max_iteration): if (df(x) == 0): exit("導數為0,迭代失敗") r = 1 x1 = x - r*f(x)/df(x) while (math.fabs(f(x1)) > math.fabs(f(x))): r = r / 2 x1 = x - r*f(x)/df(x) if (math.fabs(f(x1)) < math.fabs(f(x))): print("下山調整後,r = ", r) x1 = x - r*f(x)/df(x) print("第", iteration + 1, "次迭代,x =", x1) if(math.fabs(x1-x) <= ep): return iteration+1, x1 else: x = x1 exit("以迭代到上限值") def secant_method(x0, x1, ep=1e-05, max_iteration=500): """ 割線法求解非線性方程 :param x0: x0初始值 :param x1: x1初始值 :param ep: 精度 :param max_iteration: 最大迭代次數 :return: 迭代次數, 方程的解 """ print("割線法求解方程,精度為", ep, ",最大迭代次數為", max_iteration) print("初始值:x0 =", x0, ", x1 = ", x1) for iteration in range(max_iteration): if(math.fabs(x1-x0) <= ep): return iteration, x1 else: x2 = x1 - f(x1)*(x1-x0)/(f(x1)-f(x0)) x0 = x1 x1 = x2 print("第", iteration+1, "次迭代,x0 =", x0, ", x1 =", x1) exit("以迭代到上限值") if __name__ == "__main__": #繪製函式f(x) = x**2 - 2*x - exp(x) + 2 和函式f(x) = 0的影象函式的呼叫 plot_nonlinear_equation() #牛頓切線法函式的呼叫 count, result = tangent_method(1) print("共迭代%d次, 方程的解為%.17f" % (count, result)) #牛頓下山法函式的呼叫 count, result = downhill_method(1) print("共迭代%d次, 方程的解為%.17f" % (count, result)) # #割線法函式的呼叫 count, result = secant_method(0, 1) print("共迭代%d次, 方程的解為%.17f" % (count, result))