fzero还是fsolve?不同的结果 - 谁是正确的?

时间:2017-07-03 14:24:49

标签: matlab precision

我有一个功能

b=2.02478;
g=3.45581;
s=0.6;
R=1;

p =@(r) 1 - (b./r).^2 - (g^-2)*((2/15)*(s/R)^9 *(1./(r - 1).^9 - 1./(r + 1).^9 - 9./(8*r).*(1./(r - 1).^8 - 1./(r + 1).^8)) -(s/R)^3 *(1./(r-1).^3 - 1./(r+1).^3 - 3./(2*r).*(1./(r-1).^2 - 1./(r+1).^2)));
options = optimset('Display','off');
tic
   r2 =  fzero(p,[1.001,100])
   toc
   tic
    r3 =  fsolve(p,[1.001,100],options)
  toc

和答案

r2 =

    2.0198

Elapsed time is 0.002342 seconds.

r3 =

    2.1648    2.2745

Elapsed time is 0.048991 seconds.

哪个更容易理解? fzero返回的值不同于fsolve

2 个答案:

答案 0 :(得分:4)

您应该始终查看函数的exit标志(或输出结构),尤其是当您的结果不符合预期时。

这就是我得到的:

  • fzero(func,[1.00001,100])

    X = 4.9969
    FVAL
    EXITFLAG = 1 % fzero found a zero X.
    OUTPUT.message = 'Zero found in the interval [1.00001, 100]'
    
  • fzero(func,1.1)

    X = 1
    FVAL = 8.2304e+136
    EXITFLAG = -5 % fzero may have converged to a singular point.
    OUTPUT.message = 'Current point x may be near a singular point. The interval [0.975549, 1.188] reduced to the requested tolerance and the function changes sign in the interval, but f(x) increased in magnitude as the interval reduced.'
    

退出标志的含义在matlab文档中有解释:

 1 Function converged to a solution x.
-5 Algorithm might have converged to a singular point.
-6 fzero did not detect a sign change.

因此,根据这些信息,很明显第一个信息可以为您提供正确的结果。

为什么fzero失败

作为documented in the manualfzero通过查找符号更改来计算零:

  

尝试在x找到一个点fun(x) = 0。此解决方案是fun(x)更改sign-fzero无法找到x^2等函数根的地方。

因此,X = 1也是您的公式的解决方案,因为标志在此位置从+ inf变为-inf,如图中所示:

enter image description here

请注意,如果可能,提供搜索范围始终是一个好主意,如手册中所述:

  

以有限间隔调用fzero保证fzero将在FUN更改符号的位置附近返回值。

     

提示:使用间隔(fzero使用两个元素)调用x0通常比使用标量x0调用它更快。

替代方案:fsolve

注意,该方法是为解决多个非线性方程组而开发的。因此,它不如fzero有效(在你的情况下慢约20倍)。 fzero使用基于渐变的方法(查看manual以获取更多信息),这可能在某些情况下效果更好,但可能会陷入局部极值。在这种情况下,只要初始值大于1,函数的梯度就会给出正确的方向。因此,对于此特定函数,fsolve比具有单个初始值的fzero更强大一些,即fsolve(func, 1.1)返回预期值。

结论:一般情况下,fzero使用搜索范围而不是初始值(如果可能的话)用于单个变量,fsolve用于多个变量。如果一个方法失败,您可以尝试其他方法或另一个起点。

答案 1 :(得分:0)

正如您可以在文档中看到的那样:

  

该算法由T. Dekker发起,使用二分,割线和逆二次插值方法的组合。

因此,它对寻求解决方案的初始点和区域很敏感。因此,对于不同的初始值和范围,您得到了不同的结果。