使用根查找算法查找多个根

时间:2013-04-21 19:38:29

标签: algorithm equation-solving

找到具有多个根的方程的根的最佳方法是什么。我知道没有一种方法可以解决每个方程式,并且你必须使用多个方程式,但我找不到一个根查找算法,即使在最简单的实例中也能解决多个根。

例如:y = x^2

虽然解决这样一个基本方程的根求解算法很有帮助,但它需要能够适应一些具有两个以上根的方程。

还有一点需要注意的是,方程式不是典型的多项式,但可能是ln(x^2) + x - 15 = 0

什么是可以解决此问题的根查找算法,或者如何编辑根查找算法(如Bisection / Newton / Brent方法)来解决此问题,(假设我在牛顿和布伦特方法中是正确的)只能解决一个根。)

3 个答案:

答案 0 :(得分:1)

我会说没有通用的方法可以找到一般方程的所有根。但是,一旦指定了足够的条件,就可以尝试并设计方法。即使是简单的二次方程ax 2 + bx + c = 0也不是完全无关紧要的,因为实根的存在取决于b 2 -4ac的符号,立刻显而易见。所以有很多技术可以应用,例如Newton-Raphson,但是对于一般情况没有一般方法,特别是像ln(x 2 )+ x-15 = 0等方程式。

答案 1 :(得分:1)

底线:您需要自己隔离根。

详细信息取决于算法: 如果你正在使用二分法或布伦特法,你需要提出一组间隔,每个间隔包含一个唯一的根。 如果使用牛顿方法,你需要提出一组起始估计(因为它收敛到 a 根给定起点,并且具有不同的起点,它可能会或可能不会收敛到不同的根)。

答案 2 :(得分:1)

正如大家所说,不可能提供一般算法来查找所有或某些根(某些根大于1)。有多少根是一些?一般来说,你找不到所有的根,因为许多函数都有无限多的根。

即使像牛顿这样的方法也不总是趋同于解决方案。我倾向于喜欢一种好的,相当稳定的方法,它将在合理的情况下收敛到一个解决方案,例如已知函数改变符号的括号。你可以找到这样一个代码,它在单根上具有良好的收敛行为,但是当函数表现不佳时,仍然可以保护它基本上像一个二分方案。

因此,如果有一个不错的根发现方案,你可以尝试简单的事情,如通货紧缩。因此,考虑一个简单的函数,就像第一种贝塞尔函数。我将使用MATLAB完成所有示例,但任何在MATLAB中具有稳定良好编写的rootfinder(如fzero)的工具就足够了。

ezplot(@(x) besselj(0,x),[0,10])
grid on

enter image description here

f0 = @(x) besselj(0,x);
xroots(1) = fzero(f0,1)
xroots =
    2.4048

从图中我们可以看到第二个根在5或6左右。

现在,为该根缩小f0,创建一个基于f0的新函数,但是在xroots(1)处缺少一个根。

f1 = @(x) f0(x)./(x-xroots(1));
ezplot(f1,[0,10])
grid on

enter image description here

请注意,在此曲线中,xroots(1)处的f0的根现在已被消除,就好像它不存在一样。我们能找到第二个根吗?

xroots(2) = fzero(f1,2)
xroots =
    2.4048    5.5201

我们可以继续,但在某些时候,由于数字问题,这个方案将会失败。而且这种失败也不会太长。

更好的方案可能是(对于一维问题)使用包围方案,与采样方法相结合。我说得更好,因为它不需要修改初始函数来缩小根。 (对于2-d或更高,当然事情变得更加毛茸茸。)

xlist = (0:1:10)';
flist = f0(xlist);

[xlist,flist]
ans =
         0    1.0000
    1.0000    0.7652
    2.0000    0.2239
    3.0000   -0.2601
    4.0000   -0.3971
    5.0000   -0.1776
    6.0000    0.1506
    7.0000    0.3001
    8.0000    0.1717
    9.0000   -0.0903
   10.0000   -0.2459

如您所见,该函数在区间[2,3],[5,6]和[8,9]中有符号变化。可以在括号中搜索的rootfinder将在此处执行。

fzero(f0,[2,3])
ans =
    2.4048

fzero(f0,[5,6])
ans =
    5.5201

fzero(f0,[8,9])
ans =
    8.6537

只需查找符号更改,然后将已知括号放入根查找器中。这将提供尽可能多的解决方案,您可以找到括号。

请注意,上述方案存在严重问题。它将完全无法找到像f(x)= x ^ 2这样的简单函数的双根,因为不存在符号更改。如果你选择过于粗略的采样,那么你可能会有一个带有两个根的间隔,但你不会在端点看到符号变化。

例如,考虑函数f(x)= x ^ 2-x,它具有0和1的单根。但是如果你在-1和2处对该函数进行采样,你会发现它是正的两点。没有迹象改变,但有两个根源。

同样,NO方法可以做得很完美。你总是可以设计一个会导致任何这种数值方法失败的函数。