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

fzero or fsolve ? differents results - Who is the correct ?

我有一个功能

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 returns 与 fsolve

不同的值

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

这是我得到的:

  • 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 manual一样,fzero通过寻找符号变化来计算零:

tries to find a point x where fun(x) = 0. This solution is where fun(x) changes sign—fzero cannot find a root of a function such as x^2.

因此,X = 1 也是您公式的解,因为符号在此位置从 +inf 变为 -inf,如绘图所示:

请注意,如手册所述,尽可能提供搜索范围总是一个好主意:

Calling fzero with a finite interval guarantees fzero will return a value near a point where FUN changes sign.

Tip: Calling fzero with an interval (x0 with two elements) is often faster than calling it with a scalar x0.

替代:fsolve

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

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

如您在文档中所见:

The algorithm, which was originated by T. Dekker, uses a combination of bisection, secant, and inverse quadratic interpolation methods.

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