找到具有多个根的方程的根的最佳方法是什么。我知道没有一种方法可以解决每个方程式,并且你必须使用多个方程式,但我找不到一个根查找算法,即使在最简单的实例中也能解决多个根。
例如:y = x^2
虽然解决这样一个基本方程的根求解算法很有帮助,但它需要能够适应一些具有两个以上根的方程。
还有一点需要注意的是,方程式不是典型的多项式,但可能是ln(x^2) + x - 15 = 0
什么是可以解决此问题的根查找算法,或者如何编辑根查找算法(如Bisection / Newton / Brent方法)来解决此问题,(假设我在牛顿和布伦特方法中是正确的)只能解决一个根。)
答案 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
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
请注意,在此曲线中,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方法可以做得很完美。你总是可以设计一个会导致任何这种数值方法失败的函数。