对于单个变量方程,使用fzero和fsolve有区别吗?
答案 0 :(得分:20)
是的,有。我只想提到两者之间最直接的区别:
这是一个简单的例子:考虑函数f=x^2
。该函数对于x
的所有实际值都是非负的。它的根目录为x=0
。我们将匿名函数定义为f=@(x)x.^2;
,并尝试使用这两种方法找到根。
使用fsolve
options=optimset('MaxIter',1e3,'TolFun',1e-10);
fsolve(f,0.1,options)
Equation solved.
fsolve completed because the vector of function values is near zero
as measured by the selected value of the function tolerance, and
the problem appears regular as measured by the gradient.
<stopping criteria details>
ans =
1.9532e-04
不是零,而是接近。
使用fzero
fzero(f,0.1)
Exiting fzero: aborting search for an interval containing a sign change
because NaN or Inf function value encountered during search.
(Function value at -1.37296e+154 is Inf.)
Check function or try again with a different starting value.
ans =
NaN
无法找到零。
考虑另一个示例,函数f=@(x)x.^3;
跨越x轴并且根目录为x=0
。
fsolve(f,0.1)
ans =
0.0444
fzero(f,0.1)
ans =
-1.2612e-16
在这种情况下, fsolve
也不会完全返回0
。即使使用我在上面定义的options
,我也只能使用0.0017
来fsolve
。但是,fzero
的答案在机器精度范围内是正确的!答案的差异不是因为算法效率低下。这是因为他们的目标不同。
fzero
有一个明确的目标:找到零!简单。没有含糊不清的地方。如果它穿过x轴,则 为零,它将找到它(仅限实数)。如果它不交叉,它会发出呜呜声。
但是,fsolve
的范围更广。它旨在解决非线性方程组。通常,您无法找到这些方程的精确解,并且必须设置容差级别,在此范围内您愿意接受解决方案作为答案。因此,需要手动设置许多选项和公差来按摩确切的根。当然,你有更好的控制,但是为了找到单个var方程的零,我认为这很痛苦。在这种情况下我可能会使用fzero
(假设它穿过x轴)。
除了这一主要差异外,实施和使用的算法也存在差异。为此,我将向您推荐有关功能的在线文档(请参阅上面的链接)。
答案 1 :(得分:8)
虽然我喜欢yoda给出的答案,但我只想补充几点。是的,这两个函数之间存在差异,因为它们具有不同的基础算法。那一定有区别。所以你需要做的是理解算法!对于matlab中不同工具之间的任何比较都是如此,这两者都应该产生解决方案。
您可以将fzero视为二分的复杂版本。如果给出一个二分算法,一个包含f(x)根的区间的两个端点,那么它可以选择该区间的中点。这允许例程将间隔减半,因为现在它必须有一个包含f(x)根的新间隔。重复执行此操作,只要您的功能是连续的,您就可以确定地收敛到解决方案。
如果fzero只有一个起点,那么它会尝试找到一对支撑根的点。一旦它发生,它就遵循上述方案。
正如您所看到的,这样的方案在一个维度上可以很好地工作。但是,它不能在多个方面起作用。所以fsolve不能使用类似的方案。您可以将fsolve视为牛顿方法的变体。从起点开始,计算该位置的函数斜率。如果用直线逼近函数,那条线在哪里会过零?
基本上,fsolve使用一种方案,在这种方案中您可以在本地逼近函数,然后使用该近似值推断到一个新的位置,希望解决方案靠近该点。然后重复此方案,直到收敛为止。与fzero相比,这种方案更容易扩展到更高维度的问题。
你应该,不应该看到差异。但是,你需要了解一个方案何时成功而另一个方案失败。实际上,所使用的算法比我所描述的算法更复杂,但这些描述封装了基本思想。