一维根查找算法

在数值计算中,一维根查找算法用于求解形如f(x) = 0的方程,其中f是一个给定的函数,x是一个实变量。本文将介绍几种常用的根查找算法,并探讨如何在C#中实现它们。

互联网上可以找到许多根查找算法及其源代码。工作主要是将这些算法翻译成C#,有时稍作修改,并将它们嵌入到一个方便的框架中,类似于C++的STL。

根查找简介

计算机如何求解f(x) = 0这样的方程呢?根查找算法并不“解决”方程,而是通过迭代方法提供(在最佳情况下)一个近似解。算法从一个假定包含解的区间开始,每次迭代至少将区间长度减半(使用二分法)。当剩余区间的长度达到预定义值(称为精度)时,算法停止。

精度和迭代次数

这种方法通常效果很好。但是,有时可能无法达到精度。为了防止算法无限迭代,应该在迭代次数达到某个值(称为迭代次数)时停止算法。

使用代码

使用库非常简单。库提供了六种常用的方法,每种方法都嵌入在一个类中,该类继承自抽象的RootFinder类。

选择算法

如果有函数f的导数表达式df,可以使用牛顿-拉弗森方法。它是稳定的,并且收敛速度快。如果没有df的表达式,答案就不那么容易了。实际上,这取决于对来说最重要的是什么。二分法总能给一个好近似,但不如其他方法快。三种方法:假位置法、割线法和里德法收敛更快,但在某些情况下可能会失败。布伦特方法似乎是最有效的方法。

代码示例

假设想求解方程f(x) = 0,其中f定义如下:

private double f(double x) { return 3 * x * x - 1; }

两个解位于区间[-1; +1]。假设想要正根。别忘了算法只提供一个解。如果选择的起始区间太大,算法可能会出错,或者给出不想要的解。所以,应该从一个像[0; 1]这样的区间开始。

private double FindRoot(double x) { // 创建包含算法的根查找对象 BisectionRootFinder finder = new BisectionRootFinder(new UnaryFunction(f)); // 定义想要的根的精度 finder.Accuracy = 1.0E-04; // 防止溢出 finder.Iterations = 30; // 无需外部括号计算 double root = finder.Solve(0.0, 1.0, false); return root; }

在[0;1]区间上的根rr = sqrt(1/3)。精度确保算法提供的近似根r'将满足:Abs(r'-r) < 10e-4 (Accuracy),除非算法达到了传递给它的最大迭代次数(这里是30次)。

算法的选择

如果有函数f的导数表达式df,使用牛顿-拉弗森方法。它是稳定的,并且收敛速度快。如果没有df的表达式,答案就不那么容易了。实际上,这取决于对来说最重要的是什么。二分法总能给一个好近似,但不如其他方法快。三种方法:假位置法、割线法和里德法收敛更快,但在某些情况下可能会失败。布伦特方法似乎是最有效的方法。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485