我正在尝试实现寻根算法。我正在使用在数字配方中发现的混合牛顿-拉夫森混合算法,效果很好。但是在将根括号括起来时,我遇到了问题。
在实现寻根算法时,我意识到在某些情况下,我的函数具有1个实根,而所有其他虚部(其中几个,通常为6或9)。我唯一感兴趣的根是真实的根,因此问题不存在。问题是该函数像三次函数一样接近根,与y = 0轴点接触...
牛顿-拉普森方法需要一些不同符号的方括号,而我发现的所有方括号方法均不适用于此特定情况。
我能做些什么?在我的程序中找到该根目录非常重要...
编辑:更多问题:有时由于一些小数值错误,比如说1e-6
在某些值上的变化,“三次”函数没有真正的根,它只是虚构的,而虚构部分却可以忽略...(已通过matlab进行了检查)
编辑2:有关该问题的更多信息。
好的,我需要寻根算法。
信息我有:
Matlab对图像上函数的答案:
根源:
0.853553390593276 + 0.353553390593278i
0.853553390593276 - 0.353553390593278i
0.146446609406726 + 0.353553390593273i
0.146446609406726 - 0.353553390593273i
0.499999999999996 + 0.000000040142134i
0.499999999999996 - 0.000000040142134i
该函数是我准备的一个真实示例,我知道我想要的答案是0.5
笔记:我仍然没有完全检查你们你们给我的一些答案(谢谢!),我只是想提供所有我已经完成问题所需的信息。
最佳答案
安德(Ander),感谢您回答我的问题(关于间隔);抱歉未能及时跟进-我的工作非常忙。另外-在找到您提供的其他信息之前-我已经想到要解释很多事情如何处理并且正在考虑如何提出。但是,我现在认为您的情况并不太困难,并且由于您显然具有显式多项式表达式(各种幂的系数),我们可以在不增加其他内容的情况下进行处理。
让我们从一个简单的案例开始,以查明方法。
步骤1。
如果您有一个二阶多项式,则其导数是一阶的并且具有一个简单的零(您可以通过括号或简单地通过明确求解方程式找到它)。 (是的,我知道二阶多项式的根也有一个封闭的公式,但是为了当前的论点,让我们忘记这一点)。
然后,将二阶多项式的零位于导数零的左侧,一个位于右侧。因此,如果您还有找到原始函数的根(二阶多项式)的根的间隔,则现在有两个间隔-导数零的左边和右边,每个都有一个零。
重要的是要意识到,原始功能在每个子间隔上都是MONOTONIC的(其中一个减小,另一个增大)。因此,只需检查(sub)间隔末尾的函数值,就可以确定它们是否实际括在零中。如果不是,则在导数的零处恰好有多个零(在这种情况下为双数),如果函数在那里为零(否则,它是一个双虚根,您现在已经找到了它的实部)。
如果导数的零在总间隔之外,则间隔内最多有一个根,而您只需要检查该特定(子)间隔。
第2步。
现在考虑一个三阶多项式。
它的导数是二阶。
THAT 2阶多项式的导数又是1阶,您像以前一样进行操作,得到两个子间隔,以找到原始函数的导数的根。这两个根为您提供了三个(最多)时间间隔,您将在其中找到原始(三阶)函数的3个根。
同样在这里,您将拥有间隔(3),其中原始函数是单调的(交替增加/减少),从而使每个子间隔的分析变得非常容易。
再次,零可以重合(2或什至全部为3),并且另外可以证明是复数值(即具有非零的虚部)。案例的分析很简单:检查区间边界处的函数值,以评估是否没有符号变化(每个子区间的函数是单调的)和/或在子区间边界之一处的函数是否为零。
第4步。
用已知的多项式对此进行概括。假设-您的示例-它是6阶:
a)构造5阶导数(即将原始数降为1阶多项式)。计算它为零(在您的示例中精确为0.5)。在这种情况下,您已经完成了,但是假设您没有意识到这一点。因此,您现在有2个间隔0..0.5和0.5..1
b)构造四阶导数。在subinterval-boundaries(0,0.5,1)处检查其值
对于每个子间隔,确定其内部是否为实零。如果是这样,您可以使用找到的两个零将原始间隔重新划分为3个子间隔(您忘了5阶导数的零)。如果它们重合(在上次切割时为0.5),则坚持使用0.5(不管您是否在其中找到了四阶导数的真双零或“双虚数”),并且仍然只有2个间隔,但是为了论证,我们假设您现在有3个。
c)构造三阶导数,并像以前一样做。然后,您将有4个(最多)间隔。
d)依此类推。以这种方式处理完二阶导数后,您有5个(最多)间隔,处理完一阶导数后,您有6个间隔(或更小...),并且知道该函数在每个子间隔上都是单调的,那么您将很快确定它们中的每一个是否都有真正的根,就像通常在每个最终子间隔中使用函数的已知单调性一样。
在评估函数时添加关于数值精度的注释:
降低噪音的第一种方法(在这种情况下,可能足够)不是按照原始形式(即a6 x * 6 + a5 x * 5 + ..)所建议的方式评估函数,而是将其重写为:
a0 + x *(a1 + x *(a2 + x *(a3 + x *(a4 + x *(a5 + x * a6))))))
因此,在评估时,请继续:
tmp = a6
tmp = x * tmp + a5
tmp = x * tmp + a4
等。
如果仅进行少量重写不足以保证数值稳定性,则应在(例如)chebyshev多项式展开式中重写多项式,并用递归关系对其进行评估。两者(获取扩展并应用递归关系进行评估)都非常简单。我可以解释一下,如果您需要帮助,但是我想这里就没有必要了。
在所有情况下,您都必须考虑到一些误差,即,接受一个计算通常不会给您数学上精确的函数值。因此,评估函数在某个时刻是否为零的评估必须包括一些“公差”,不幸的是,没有办法解决这个问题。您可以寻求的最好的办法就是将噪音降到最低。