Python 中的割线法建模


割线法是用于求解多项式或任何超越函数的 x 截距(零点)的强大方法之一。在这种方法中,我们首先选择(基本上是猜测)我们期望根所在的区间($\mathrm{𝑥_{1}}$,$\mathrm{𝑥_{2}}$)。然后,我们绘制一条割线以连接对应于猜测值的函数上的点(A,B),如下图所示。

割线与 x 轴相交于点 $\mathrm{𝑥_{3}}$,由于 $\mathrm{𝑥_{3}}$ 和 $\mathrm{𝑥_{2}}$ 不接近(即它们的绝对差是有限的),我们找到对应于 $\mathrm{𝑥_{3}}$ 曲线上的点,即 C。然后,我们考虑点 B 和 C 连接一条割线。我们将这条线延伸到到达 X 轴,并将该点标记为 $\mathrm{𝑥_{4}}$。

现在,我们再次检查 $\mathrm{𝑥_{3}}$ 和 $\mathrm{𝑥_{4}}$ 是否接近。由于它们也不接近,因此我们找到对应于 $\mathrm{𝑥_{4}}$ 的多项式的值,并在曲线上将其标记为 D。下图表示第二条割线和点 D。

然后,我们再次在 C 和 D 之间绘制一条割线,直到“x”的下一个值和前一个值的距离收敛到一个非常小的值。因此,我们可以说该方法依次找到多项式的根,即它可以被认为是根的顺序搜索。这种方法的优点在于,x 是否位于根的一侧或围绕根并不重要。该方法通过上述解释的顺序搜索逐渐收敛到根。

现在,任务是根据前两个 x 来评估下一个 x。如果我们考虑第一条割线,那么通过它们(以评估 $\mathrm{𝑥_{3}}$)的直线方程如下:

$$\mathrm{x_{3}=x_{1}-y_{1}\frac{x_{2}-x_{1}}{y_{2}-y_{1}}}$$

而如果我们考虑第二条割线,则用于评估的直线方程如下:

$$\mathrm{x_{4}=x_{2}-y_{2}\frac{x_{3}-x_{2}}{y_{3}-y_{2}}}$$

因此,上述方程的广义版本如下:

$$\mathrm{x_{i}=x_{i-2}-y_{i-2}\frac{x_{i-1}-x_{i-2}}{y_{i-1}-y_{i-2}}}$$

Python 中的割线法实现

可以使用以下算法对割线法进行建模:

  • 首先需要定义需要求根的函数 f(x)

  • 选择两个任意 x 值,即 ($\mathrm{𝑥_{1}}$,$\mathrm{𝑥_{2}}$)

  • 使用以下公式评估 x 的新值 $$\mathrm{x_{n}=x_{1}-f(x_{1})\frac{x_{2}-x_{1}}{f(x_{2})-f(x_{1})}}$$

  • 如果 x 的新值和前一个值接近,则得到答案,即如果 $|x_{n_{}}-x2|<10^{-5}$,则 $𝑥_{𝑛}$ 是根。注意,我们取收敛准则为 $10^{-5}$,但您可以根据您的需要进行设置。

  • 如果 $|x_{n_{}}-x2|>10^{-5}$,则设置:$𝑥_{1}$=$𝑥_{2}$ 和 $𝑥_{2}$=$𝑥_{𝑛}$

  • 然后再次从评估新 x 的步骤开始。

然后再次从评估新 x 的步骤开始。

假设我们想要找到方程:$𝑥^{2}$+3𝑥−10=0 的根。让我们选择初始值为 ($𝑥_{1}$=−4,$𝑥_{2}$= 3)。然后执行割线法的 Python 程序如下:

# Importing module
from pylab import *

# Defining Polynomial function
def f(x):
   return x ** 2 + 3 * x - 10

# Defining function for new value of x
def fn(a, b):
   return a - ((b - a) / (f(b) - f(a))) * f(a)

# Creating array of x
x = linspace(-15, 15, 150)

# Plotting the function
figure(1, figsize=(7.20, 3.50))
plot(x, f(x), linewidth=2)
plot([-25, 25], [0, 0], "k--")
ylim(-15, 20)
xlim(-8, 6)

# Initial guess Interval
x1 = -4
x2 = 3

# Initial Error to enter into the loop
error = 1

# Setting iteration counter
count = 1

# Integration starts
while error > 1.E-3:

   # Plotting Secant line
   plot([x1, x2], [f(x1), f(x2)])

   # Evaluating new value of x based on old
   xn = fn(x1, x2)

   # Plotting x intercept of secant
   plot([xn], [0], 'o', label=f'{xn}')

   # Evaluating error
   error = abs(x2 - xn)

   # Setting x's for next iteration
   x1 = x2
   x2 = xn

   # Incrementing loop counter
   count += 1

   # Printing selected value of xn in the legend
   if count < 6:
      legend()

# Showing root in the figure (just decoration)
text(-7, -10, f'Root = {round(xn, 3)}', bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})
print(f'Root = {round(xn, 3)}')
show()

上述代码清楚地说明了本节开头提到的所有步骤。上述程序的输出将如以下图所示。

对于其他根,您可以将初始“x”取为:−6 和 −2。然后结果如下所示

结论

本文详细讨论了割线法。给出了数学背景,以便轻松地对该方法进行建模。用户可以修改上面给出的代码,并使用它来查找其他函数的根。

更新于: 2023 年 3 月 15 日

2K+ 阅读量

开启您的 职业生涯

通过完成课程获得认证

立即开始
广告