目录
一、数值分析
1.主要内容
数值分析包括的主要内容有:插值法,函数逼近,曲线拟合,数值积分,数值微分,解线性方程组的接直解法,解线性方程组的迭代法,非线性方程求根,微分方程的数值解法。
2.特点
(1)面向计算机
(2)有可靠的理论分析
(3)要有好的计算复杂性
(4)要有数值实验
(5)要对算法进行误差分析
在数值分析模型中,这些都是需要考虑并理解的重要概念。通过数值分析,我们可以完成许多在解析形式下无法解决的问题,但这也引入了误差和近似,因此需要适当的策略和注意事项来管理这些问题。
二、插值法
1.概念
插值法指的是根据已知数据点的信息,通过建立适当的插值函数或曲线,估计在未知数据点上的数值。插值是一种逼近技术,用于估计缺失数据或填补数据间的间隔。插值法可以用于处理连续变量的数据,如时间序列分析、地理信息系统等领域。常见的插值方法包括线性插值、拉格朗日插值、牛顿插值、样条插值等。插值法的原理是基于已知数据点之间的连续性假设,通过插值函数或曲线来近似描述未知数据点之间的关系。插值法可以帮助我们填补数据缺失、平滑数据、预测未来数据等。
2.拉格朗日插值法
拉格朗日插值(Lagrange Interpolation)是一种多项式插值法,它是通过构造过N个点的多项式函数P(x),并且使得P(x)能够在指定几点上准确等于函数的值。
给定n+1点(x0, y0), (x1, y1), ..., (xn, yn)其中所有的xi都是不同的,拉格朗日插值的标准形式如下:
其中 Li(x) 是 拉格朗日基础多项式,定义如下:
这样,Li(xi) = 1,并且对于所有的j != i, Li(xj) = 0. 这保证了只有i等于j时,yi在多项式中起作用;当i不等于j时,yi对多项式没有贡献。
Python代码实现
下面是一个利用拉格朗日插值法进行函数插值的示例Python代码。
import numpy as np
import matplotlib.pyplot as plt
# 拉格朗日插值函数
def lagrange_interpolation(x_points, y_points, x):
# 初始化拉格朗日插值多项式
lagrange_poly = 0
n = len(x_points)
# 计算拉格朗日多项式的值
for i in range(n):
# 初始化基多项式为1
basics_poly = 1
for j in range(n):
if i != j:
# 乘以基多项式的因子
basics_poly *= (x - x_points[j]) / (x_points[i] - x_points[j])
# 将基多项式乘以对应的 y 点并相加
lagrange_poly += basics_poly * y_points[i]
return lagrange_poly
# 已知的数据点
x_points = np.array([0, 1, 2, 3, 4, 5])
y_points = np.array([1, 2, 1, 0.5, 4, 8])
# 待插值的 x 值
x = np.linspace(min(x_points), max(x_points), 100)
# 计算拉格朗日插值多项式在 x 处的值
y = np.array([lagrange_interpolation(x_points, y_points, xi) for xi in x])
# 绘图展示
plt.figure(figsize=(10, 6))
plt.plot(x, y, label="Lagrange Interpolation")
plt.plot(x_points, y_points, 'ro', label="Data Points")
plt.title("Lagrange Interpolation Example")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.grid(True)
plt.show()
这段代码首先定义了一个名为lagrange_interpolation
的函数,它接受插值点x_points
、对应的函数值y_points
和插值位置x
作为参数,然后返回在x
处的拉格朗日插值多项式的值。
在给出的例子中,我们有一组已知的点x_points
和对应的y_points
。然后,我们在这些点的范围内生成了一个分辨率较高的x
值,以便计算插值结果,并用matplotlib绘制图形来展示插值曲线和已知点的分布。
请注意,如果我们的插值点过多,拉格朗日插值多项式可能会产生数值不稳定的问题(Runge现象)。
龙格现象
龙格现象(Runge's phenomenon)是指在使用高阶多项式进行插值时,在插值区间的边缘附近,特别是对于等距节点而言,插值多项式可能会出现严重的振荡,这种振荡导致插值多项式与实际函数之间的差异增大,尤其是在区间的末端。
龙格现象产生的影响如下:
-
准确性降低:插值多项式在插值节点接近实际函数值时准确,但是在节点间的区域,特别是接近区间端点的部分,可能与真实函数的值偏差很大。
-
振荡:插值多项式在区间的两端出现强烈的振荡,即使在函数本身平滑的部分也会出现这种现象。
-
不适于外推:由于高阶插值多项式在插值区间外表现不稳定,因此它们不适合用于外推,即预测函数在已知数据点外的值。
-
问题增加:在追求插值精度的过程中,可能会不断增加插值点的数量,这反而能导致问题的恶化,因为多项式度数的提高会加剧振荡现象。
为了避免龙格现象,有以下三种方法可以解决:
-
使用分段低阶插值:例如分段线性插值或三次样条插值,可减小高阶多项式插值带来的问题。
-
使用切比雪夫节点:这些节点是非等距的,它们在区间内更密集,而在区间两端更稀疏,从而有助于减少插值多项式的振荡。
-
应用最佳逼近多项式:例如通过最小二乘法拟合一个多项式,这种方法通过最小化就整个区间的误差,而不是仅在插值点上误差为零。
龙格现象如下图所示:
注:红色的是原式
3.二次插值
二次插值法是一种数学上的插值方式,特别是在给定的数据点稀疏时,它可以用来估计未知点的值。在二次插值中,我们使用一个二次多项式(即最高次项为x的平方的多项式)来近似数据。二次多项式的一般形式为:
其中,a、b 和 c 是多项式的系数,它们可以通过插值条件——即已知的数据点——来确定。
为了构建一个通过三个给定点 , , 的二次插值多项式,我们可以设置以下方程系统:
该方程组可以使用代数方法解决,比如解线性方程组的克拉默法则(Cramer's Rule)或者高斯消元法(Gaussian Elimination)。解出 a、b、c 后就得到了满足以上三个数据点的二次插值多项式。
这个多项式可以用于计算任何其他的x值对应的近似y值。例如,如果我们想要计算一个新的点 的y值,那么只需要将x值代入我们找到的插值多项式 中即可得到。
二次插值在数据点较少的情况下是很有用的,但它可能不适用于具有多个波动或者更高程度复杂性的函数形态。当涉及更多的数据点时,可能需要考虑更高阶的多项式或其他形式的插值方法,如分段插值或样条插值法。二次插值同样可能受龙格现象的影响,尤其是对于等距节点的高阶插值。
Python代码实现
下面是一个基本的二次插值法的Python代码实现:
import numpy as np
import matplotlib.pyplot as plt
def quadratic_interpolation(x_points, y_points, x):
# 检查点的数量是否足够进行二次插值
if len(x_points) != 3 or len(y_points) != 3:
raise ValueError("There must be exactly three points for quadratic interpolation.")
# 计算二次插值系数
# 解二次方程组来找到 a, b, 和 c
A = np.array([
[x_points[0]**2, x_points[0], 1],
[x_points[1]**2, x_points[1], 1],
[x_points[2]**2, x_points[2], 1]
])
b = y_points
# 使用numpy的线性代数求解器求解系数
coef = np.linalg.solve(A, b)
# 插值多项式的系数
a, b, c = coef
# 根据二次多项式计算插值结果
return a*x**2 + b*x + c
# 定义已知点
x_points = np.array([-1, 0, 2])
y_points = np.array([1, -1, 7])
# 待评估的点
x_values = np.linspace(min(x_points)-1, max(x_points)+1, 100)
y_values = quadratic_interpolation(x_points, y_points, x_values)
# 绘制结果
plt.plot(x_values, y_values, label='Quadratic Interpolation', color='blue')
plt.scatter(x_points, y_points, color='red', label='Data points')
plt.legend()
plt.xlabel('x')
plt.ylabel('y')
plt.title('Quadratic Interpolation Example')
plt.grid(True)
plt.show()
这个代码块定义了一个quadratic_interpolation
函数,它接受三个已知的数据点x_points
和y_points
以及一个用于插值的点x
。系数a
、b
和c
是通过解线性方程组得到的,该方程组是根据三个数据点构建的。
该函数然后用插值点x_values
来计算对应的插值y_values
,最后使用Matplotlib绘制出插值结果以及原始数据点。这个插值曲线将通过所有已知点,形成一个拟合这些点的二次曲线。
4.n次插值
n次插值法,也称为多项式插值法,是一种通过已知的n+1个数据点来构造一个n次多项式的方法。在数学和工程中,多项式插值法允许我们构造一个简单的代数方程,这个方程可以在整个定义域内无限逼近一个复杂的函数。
对于给定的n+1个数据点 , ,..., ,其中所有的都是互不相同的,n次插值法旨在找到一个n次多项式 ,满足:
对于所有的 。这样的多项式可以表达为:
为了确定多项式的系数 ,需要解一个由n+1个线性方程组成的方程组,这些方程是基于上面的n+1个数据点。
具体求解系数的过程如下:
-
建立方程:我们将每个数据点 代入多项式 中,得到n+1个方程。
-
矩阵表示:将这些方程写成矩阵的形式,这将形成一个方程组,我们可以用线性代数的方法求解。
-
求解方程:这个方程组通常通过高斯消元或者其他数值方法来求解。系数一旦被确定,多项式的形式就被完全定义。
然而,当插值点的数量增加时,n次多项式插值可能会遇到运算复杂和数值不稳定的问题。这种情况下,通常会采用分段插值方法,比如线性插值、Hermite
5.牛顿插值法
牛顿插值法是一种流行的插值方法,它可以有效地构造一个通过一组给定数据点的多项式。和拉格朗日插值法相比,牛顿插值法的一个优势是插值多项式可以逐步构造,这使得在添加新的数据点时不需要从头计算整个插值多项式。
牛顿插值多项式的形式如下:
其中, 是数据点的横坐标, 是多项式的系数,它们通过构造差商表(divided difference table)来计算得出。
差商(Divided Differences)
差商是牛顿插值中的一个重要概念,它类似于导数,但适用于离散数据点。给定一组数据点 ,,... , 零阶差商就是数据点的纵坐标 。高阶差商通过以下递归定义:
对于第一个系数 ,它等于 ;而 是 ,依此类推。通过计算所有所需的差商,我们可以得到插值多项式各项的系数。
牛顿插值的步骤
- 给定数据点集。
- 计算每个系数所需的差商。
- 构造牛顿插值多项式。
- 使用多项式对任何其他的 值进行插值,预测其值。
牛顿插值法的一个重要优点是它的灵活性。如果我们添加了一个新的数据点,我们只需要计算相关的差商并添加一个新项到现有的牛顿插值多项式中,而不是重新计算整个多项式。这种属性在实际应用中非常有用,特别是在逐步接收数据并需要持续更新插值模型时。
Python代码实现
下面是一个牛顿插值的Python代码实现:
import numpy as np
import matplotlib.pyplot as plt
# 计算分差
def divided_diff(x, y):
n = len(y)
coef = np.zeros([n, n])
# 第一列为y值
coef[:,0] = y
# 计算分差
for j in range(1,n):
for i in range(n-j):
coef[i][j] = (coef[i+1][j-1] - coef[i][j-1]) / (x[i+j] - x[i])
# 返回分差的第一行
return coef[0,]
# 计算牛顿插值多项式值
def newton_poly(coef, x_data, x):
n = len(x_data) - 1
p = coef[n]
for k in range(1, n+1):
p = coef[n-k] + (x - x_data[n-k])*p
return p
# 已知的数据点
x = np.array([0, 1, 2, 5, 6, 7], dtype=float)
y = np.array([-1, 2, 0, 2, 1, 0], dtype=float)
# 计算分差,获取牛顿插值多项式系数
coef = divided_diff(x, y)
# 使用牛顿插值多项式对数据进行插值
x_new = np.linspace(np.min(x), np.max(x), num=100)
y_new = [newton_poly(coef, x, xi) for xi in x_new]
# 绘制插值曲线
plt.figure(figsize=(10, 5))
plt.plot(x_new, y_new, 'r-', label='Newton Interpolated')
plt.plot(x, y, 'bo', label='Data points')
plt.title('Newton Interpolation')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()
此代码首先定义divided_diff
函数计算分差表,并返回牛顿插值多项式的系数。然后newton_poly
函数利用这些系数与给定的数据点,计算牛顿插值多项式在特定x值上的值。
在以上例子中,我们定义了一组特定的数据点x
和y
,并使用牛顿插值法来建立一个插值多项式。然后,我们使用这个多项式在一个比原始数据点范围更广的x值范围上进行了插值,最后通过绘图展示了原始数据点和插值曲线。
三、非线性方程求根
1.求根的对区间法
求根的对分区间法(Bisection Method)是一种基本的数值算法,用于求解实数域上连续函数的根。这个方法的关键思想是使用二分查找策略来迭代地缩小包含函数根的区间范围。它基于中值定理,即如果函数在区间的两端取不同符号的值,则该区间内至少存在一个根。下面是对分区间法的具体步骤:
-
确定初始区间:
选择一个闭区间 [a, b],使得函数 f 在 a 和 b 两点的函数值 f(a) 和 f(b) 有不同的符号,即 f(a)·f(b) < 0。这表明在区间 [a, b] 内至少存在一个根。 -
计算中点的函数值:
找到区间 [a, b] 的中点 c = (a + b) / 2,并计算该点的函数值 f(c)。 -
确定新区间:
根据中点的函数值,可以确定根位于哪个子区间:- 如果 f(a)·f(c) < 0,则根位于区间 [a, c] 内,于是我们将 b 更新为 c。
- 如果 f(c)·f(b) < 0,则根位于区间 [c, b] 内,于是我们将 a 更新为 c。
-
迭代过程:
重复上述过程,每次都重新计算新区间的中点和该点的函数值,并更新 a 或 b 的值,以此缩小包含根的区间。 -
停止条件:
对分区间法的迭代一般会在满足以下一种或多种停止条件时结束:- 子区间的长度 |b - a| 小于给定的容差 ε(例如,ε = 0.001)。
- 中点的函数值 f(c) 的绝对值小于某个预设的阈值 δ,即 |f(c)| < δ。
- 迭代次数达到了设定的最大迭代数。
由于在每步迭代中区间长度都减半,对分区间法的收敛速度是线性的,即每迭代一次,解的位数大约增加一个(以二为底)。这种算法的优点是简单、可靠,并且对于任何连续函数都必定收敛到一个根。缺点是收敛速度比较慢,特别是对于区间较宽或者求解精度要求较高的情况。
在实践中应用对分区间法时,重要的是初步选择一个正确的区间 [a, b] 并确保在该区间内有根存在。此外,由于收敛速度的问题,该方法通常不适用于精确度要求极高或者函数计算成本较高的情况。
四、迭代法
1.简单迭代法
简单迭代法,也被称为不动点迭代法(Fixed-Point Iteration)或者函数迭代法,是求解函数方程的一种数值方法。当我们无法直接解出方程的根时,可以通过迭代的方式来逼近解。简单迭代法的出发点是将原始的方程 f(x)=0 转换为等价的形式 x = g(x)。在这里,g 是一个在我们感兴趣的区间内定义的函数,我们要找到这样一个点 x*,使得 g(x*) = x*,即 x* 是函数 g 的不动点。
基本步骤:
1.1. 方程重写
首先,需要将原始方程 f(x)=0 转换为等价的 x=g(x) 形式。这个步骤可能涉及到数学上的一些技巧以确保转换后的方程满足迭代求解的需要。
1.2. 选择初始猜测
选择一个合适的初始值 x0。这个值是迭代的起始点,理想情况下应该尽量靠近真实根。
1.3. 迭代规则
应用迭代公式 xi+1 = g(xi),从初始猜测 x0 开始,依次计算 x1, x2, x3,...,其中 i 表示迭代的次数。
1.4. 收敛性检验
对于新产生的 xi+1,检查与前一步的 xi 的差值是否小于预设的阈值 ε:|xi+1 - xi| < ε。如果满足这个条件,迭代停止,因为我们认为对应的 xi+1 就是方程的根的一个近似解。
1.5. 重复迭代
如果第 4 步的检验没有通过,则继续重复第 3 步和第 4 步,直到收敛条件满足或者迭代次数超出了预设的最大迭代次数。
为了确保迭代法的有效性,函数 g(x) 必须在我们考虑的区间内满足一定的条件。最重要的是它必须满足 Lipschitz 条件,即存在一个常数 L < 1,对于区间内的所有 x 和 y,有 |g(x) - g(y)| <= L|x - y|。这个条件保证了函数 g(x) 在区间内 "压缩" 的性质,这是保证迭代序列收敛的关键。
这种方法的一个关键优点是它的简单性;它不需要复杂的数学运算,通常也不需要知道 f(x) 的导数。但是它的缺点是可能会发生慢速收敛甚至不收敛,特别是当初始猜测距离真实根较远时。选择一个好的初始猜测和一个合适的 g 函数对成功使用简单迭代法至关重要。
2.牛顿迭代法
牛顿迭代法(Newton-Raphson method)是一种强大的数值技术,用于寻找实数函数的根,特别是那些难以通过解析方法求解的根。这种方法依赖于函数的导数,它利用函数图形的切线来估计函数的根,并迅速地逼近这些根。以下是牛顿迭代法的详细介绍:
起源与原理
牛顿迭代法基于牛顿(Isaac Newton)和拉弗森(Joseph Raphson)的工作。其核心思想是使用函数在某一点的一阶泰勒展开(即切线)来估计零点的位置。如果函数 f(x) 在点 x=r 有根,则 f(r)=0。牛顿迭代法试图通过迭代逼近这个 r。
基本步骤
-
选择初始近似值:
选择一个接近函数根部的初始近似值 x₀。一个好的选择可以显著提高收敛速度。 -
迭代公式:
迭代公式可以用下面的式子表示:
其中,xₙ 是当前的近似值,xₙ₊₁ 是下一个更接近实际根的值。 -
应用迭代公式:
将当前的近似值 xₙ 代入 f(x) 和 f'(x),求得下一个近似值 xₙ₊₁。 -
收敛判断:
继续迭代直至满足一定的停止准则,通常是相邻两次迭代之间的差别非常小:|xₙ₊₁ - xₙ| < ε,其中 ε 是一个很小的正数,表示容许误差。
例子
假设我们想要寻找 f(x) = x² - 2 的根,其导数是 f'(x) = 2x。初始估计 x₀ 可以是 1。根据迭代公式,计算过程如下:
重复这个过程,可以得到越来越准确的结果。
收敛性
牛顿迭代法的收敛速度通常很快,特别是当开始的近似值已经比较接近真实根时。理想情况下,该方法的收敛速度是平方的,意味着每做一次迭代,有效数字大约翻倍。但是,这种收敛速度也依赖于函数的性质和选取的起始点。收敛性可能会受到起始点的选择、函数在根附近的行为(如导数接近0)以及迭代过程中可能遇到的数值问题的影响。
注意事项
- 如果初始估计不佳或者函数在根附近的导数值很小,牛顿法可能不收敛。
- 如果函数 f(x) 的导数不存在或在某处为零,牛顿法会失败。
- 存在使用牛顿法寻找函数多个根的可能性,因此可能需要多个初始估计值。
牛顿迭代法广泛应用于科学工程计算以及各类数学分析中,因其简洁和强大的收敛性成为求解方程经典且重要的方法之一。
3.牛顿下山法
牛顿下山法(也被称为衰减步长的牛顿法或线搜索牛顿法)是一种修改版的牛顿迭代法,用于寻找函数的根或者计算多维空间中的最优点。当标准的牛顿迭代法因某种原因无法保证收敛性时,牛顿下山法通过调整迭代步长来提高方法的稳定性和可靠性。
在某些情况下,标准牛顿迭代法可能因为迭代步长太大或在函数图形中存在尖锐的弯曲导致迭代结果发散。牛顿下山法通过在每一步的迭代中引入一个步长参数来解决这个问题。这个步长参数使得迭代过程在必要时能够采用更小的步伐前进,从而避免过度跳跃或陷入无助的状态。这种策略类似于一个登山者在山陡峭时减慢脚步谨慎前进以避免滑倒。
基本思想
牛顿下山法的迭代过程不是直接向着标准牛顿法的方向前进,而是乘以一个标量 α 来控制步长。该方法迭代公式如下:
其中,α ∈ (0, 1]。α 的选择取决于函数在当前点的行为。如果直接使用标准牛顿法的步伐会使得函数值增大,那么就减小 α。
算法步骤
- 选择初始近似值 x₀,设置容差 ε 和步长 α。
- 迭代公式:计算 x_{n+1} = x_n - α * (f(x_n)/f'(x_n))。
- 线搜索策略:如果直接应用标准牛顿步长导致无法获得更好的近似值,则减小步长 α。
- 收敛判断:如果 x_{n+1} 与 x_n 的差别足够小,或者函数值的减小量足够小,即小于 ε,则认为找到了根或者最优点并停止迭代。
- 步长更新:如果没达到收敛条件,需要根据具体情况调整 α 值。
- 反馈更新:用新值 x_{n+1} 替换 x_n ,回到步骤2继续迭代。
特点
- 收敛性:降低步长可以提高算法的稳定性和收敛性。
- 鲁棒性:避免迭代过程中可能出现的发散现象,特别是在迭代点附近函数曲线弯曲较为急剧时。
- 收敛速度:通过调整步长可改善收敛速度,但较小的步长可能导致算法收敛过慢。
牛顿下山法特别适用于解决函数导数变化较大或初步估计值距离实际根较远的情形,在这些情况下,传统的牛顿法可能无法收敛。通过引入步长控制,牛顿下山法增加了算法的灵活度和适用范围。然而,在实际应用中,选择合适的步长策略和调整步长的方法是实现该算法关键所在。
五、弦截法和抛物线法
弦截法和抛物线法都是数值方法中用于寻找函数根的迭代算法。它们可以视为牛顿迭代法的变体,适用于那些难以通过解析方法求解根的方程。下面分别介绍这两种方法的原理和过程。
弦截法
弦截法(Secant Method)是一种不需要函数的导数就能估算方程根的方法。这个特性使弦截法在不易求导的情况下,成为一个十分有用的工具。具体步骤如下:
-
选择两个初始点:选择两个初始近似值 x₀ 和 x₁,它们足够靠近所要找的根。
-
计算新点:使用这两点来估算函数图形的弦。弦与 x 轴的交点被视为下一个近似解。迭代公式为:
-
迭代:使用新的近似值代替旧的值,并重复上述过程。
-
收敛判断:当连续两个近似值之间的差值小于预定的容忍值时,停止迭代。
弦截法与牛顿法类似,但不直接使用导数而是使用两个近似点来估计导数。它的收敛速度通常比牛顿法慢,且可能因选择的初始点不合适而不收敛。
Matlab代码实现
以下是一个基本的弦截法(Secant Method)实现的 MATLAB 代码示例,用于寻找函数 f(x) = 0 的根:
function root = secantMethod(func, x0, x1, tol, max_iter)
% secantMethod: 使用弦截法寻找方程的根
% func - 输入函数句柄
% x0 - 第一个近似解
% x1 - 第二个近似解
% tol - 容忍误差, 迭代停止的条件
% max_iter - 最大迭代次数
iter = 0; % 初始化迭代次数
while true
% 计算根的近似值
fx0 = func(x0);
fx1 = func(x1);
x2 = x1 - (fx1 * (x1 - x0)) / (fx1 - fx0);
% 检查收敛性
if abs(x2 - x1) < tol || iter >= max_iter
break;
end
% 更新迭代前的两个点
x0 = x1;
x1 = x2;
iter = iter + 1;
end
% 输出根的近似值
root = x2;
fprintf('The root found is: %f\n', root);
fprintf('Number of iterations: %d\n', iter);
end
使用该函数的例子:
% 定义目标函数
func = @(x) x^2 - 2; % 示例函数 x^2 - 2
% 定义初始近似值
x0 = 0; % 第一个近似解
x1 = 2; % 第二个近似解
% 设定容忍误差和最大迭代次数
tol = 1e-6; % 容忍误差
max_iter = 100; % 最大迭代次数
% 调用弦截法函数寻找根
root = secantMethod(func, x0, x1, tol, max_iter);
上述代码是一个简单的弦截法实现,它以函数句柄(func)、两个初始近似值(x0 和 x1)、容忍误差(tol)和最大迭代次数(max_iter)作为输入,计算并返回方程的一个近似根。在实际使用时,我们可能需要根据具体问题调整这些参数以及增加额外的错误检查或特殊情况的处理。
抛物线法
抛物线法(Method of False Position 或 Regula Falsi Method)是一种在确定了函数的根位于某个区间的前提下,以弦截法的思想进行迭代的方法,但它在每次迭代时总是保留函数值异号的两个点,以确保根被框定于一个不断缩小的区间内。具体步骤如下:
-
选择初始区间:选择两个初始点 x₀ 和 x₁,这两点满足 f(x₀) * f(x₁) < 0,即它们在 x 轴的两侧。
-
计算新点:计算这段区间的弦与 x 轴的交点作为新的近似解。迭代公式与弦截法相同。
-
保留异号点:选取带来异号函数值的点和新计算出的近似点作为下一步迭代的两个点。
-
迭代:重复上述过程,直到满足收敛条件。
-
收敛判断:通常采用两个点的距离小于预定容忍值或函数值足够接近零作为停止条件。
抛物线法是一种保守的迭代方法,它比弦截法慢,但是收敛性通常更好,因为它保持了根在一个区间内的性质。
两种方法都用于那些难以解析求解的方程,它们提供了在给定的初始估计不是特别好时,或者当导数难以计算或不存在时的有效的迭代方案。在实际运用中,它们可以根据特定问题的特点和计算资源来选择使用。
Matlab代码实现
抛物线法的MATLAB代码实现如下。这个实现旨在通过迭代过程找到函数f(x)的根。
function root = regulaFalsi(func, a, b, tol, max_iter)
% regulaFalsi 使用抛物线法找到函数的根
% func - 目标函数
% a, b - 根所在区间的初始端点,满足 func(a) * func(b) < 0
% tol - 容忍限
% max_iter - 最大迭代次数
fa = func(a);
fb = func(b);
if fa * fb > 0
error('Function does not have opposite signs at the endpoints a and b.');
end
for iter = 1:max_iter
% 根据抛物线法的公式计算新的近似根
root = (a * fb - b * fa) / (fb - fa);
froot = func(root);
% 打印当前迭代信息
fprintf('Iteration %d: root = %f, f(root) = %f\n', iter, root, froot);
% 检查收敛性
if abs(froot) < tol
fprintf('Converged to a root: %f after %d iterations.\n', root, iter);
return;
end
% 依据函数值的异号选择新的区间进行下一次迭代
if froot * fa < 0
b = root;
fb = froot;
else
a = root;
fa = froot;
end
end
% 如果到达最大迭代次数还没找到根,则返回失败信息
fprintf('Method failed to converge after %d iterations.\n', max_iter);
root = NaN;
end
使用这个函数的例子:
% 定义目标函数,例如x的平方减2
func = @(x) x^2 - 2;
% 定义初始区间,这个区间内应该包含根
a = 0; % 区间的左端点
b = 2; % 区间的右端点
% 设定容忍误差和最大迭代次数
tol = 1e-6;
max_iter = 100;
% 调用抛物线法函数寻找根
root = regulaFalsi(func, a, b, tol, max_iter);
这段代码会在给定区间内寻找函数func
的根,直到函数值的绝对值小于tol
,或者迭代次数达到max_iter
。抛物线法假设在区间内函数func
至少有一个根,并且func(a)
和func(b)
有不同的符号。记住要根据实际使用场景对代码进行适当的修改和调整。
总结
还是比较详细的对吧,再见啦~~~~