声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 4043|回复: 2

[编程技巧] 请教一个fzero命令的小问题,拜托?

[复制链接]
发表于 2007-3-12 18:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
我在解非线性方程的时候遇到一些困难,简单举一个“小示例”来说明:


请问如何将主程序里的值在fzero里赋给子程序而不出错?
另外如fsolve命令又如何赋值呢?  谢谢!

% 分别将3 2 5 赋值给 a b c
z=fzero(@y,2,[],3,2,5)

function y=f(x,a,b,c)
y=x^a-b*x-c;

%

z=fzero(@y,2,[],3,2,5)
Warning: Cannot determine from calling sequence whether to use new or
grandfathered FZERO function.  Using new; if call was grandfathered
FZERO syntax, this may give unexpected results.

> In C:\MATLAB6p1\toolbox\matlab\funfun\fzero.m (parse_call) at line 412
  In C:\MATLAB6p1\toolbox\matlab\funfun\fzero.m at line 103

z =

    2.0946

[ 本帖最后由 eight 于 2007-3-12 18:52 编辑 ]
回复
分享到:

使用道具 举报

发表于 2007-3-12 20:00 | 显示全部楼层
matlab7.0的可以
z=fzero(@f,2,[],3,2,5)

z =

    2.0946

评分

1

查看全部评分

发表于 2007-3-12 21:11 | 显示全部楼层
Subject:Why do I receive a warning message when using FZERO in MATLAB 5.3 (R11) or higher?
Problem Description:The code I'm using works fine in MATLAB 5.2 (R10).  Here's the warning I received:
fzero('fun',x0,[],[],1)


Warning: Cannot determine from calling sequence whether to use new or
grandfathered FZERO function.  Using new; if call was grandfathered
FZERO syntax, this may give unexpected results.
  
Solution:This enhancement has been made for Release 14 (R14). For previousproduct releases, please read below for any possible workarounds:

Thesyntax for FZERO has changed in MATLAB 5.3 (R11) to make this functionmore consistent with other optimization/minimization functions. Westrongly suggest using the newer version and syntax of FZERO, but youcan still use the older version of FZERO if you wish. When in MATLAB,type:
doc fzero


to see more details on the new usage. Basically, instead ofsupplying two empty arguments, if you want to use the default settingsyou can use the following:
fzero('fun',x0,[],p1);


By leaving the third input empty, you're requesting that thedefault options be used. With FZERO, this will produce a warningindicating that the calling syntax is ambiguous, but will usuallyproduce the answer you're expecting.

In MATLAB 5.3 (R11), thetolerance and trace are specified inside the options structure, whichis the third input parameter. To choose the defaults, use the followingsyntax:
fzero('fun',x0,optimset('fzero'),p1)


or in two separate lines:
options=optimset('fzero');
fzero('fun',x0,options,p1);


If you must use the older version, you'll need to use the old FZEROcode from MATLAB 5.2 (R10). You may want to rename the old "fzero.m"file to "fzero_old.m" and then use the "Search and Replace" feature inyour M-file editor to change calls to "fzero" to calls to "fzero_old".Though this isn't necessary and you can use the name FZERO, if you givethe older version a different name you are less likely to affect otherM-files which rely on the newer FZERO. The older FZERO code is listedbelow at the end of this solution.

You should also be aware thatwe've stablized the older FZERO code and are no longer making changesto it. If you run into problems with it you may want to try using thenewer version to see if they have been corrected there.

Below is the FZERO code used with MATLAB 5.2 (R10):
function b = fzero(FunFcn,x,tol,trace,varargin)
%FZERO  Find zero of function of one variable.
%   FZERO(F,X) tries to find a zero of F.  F is a string containing
%   the name of a real-valued function of a single real variable.   
%   The value returned is near a point where F changes sign, or NaN
%   if the search fails.  
%
%   FZERO(F,X), where X is a vector of length 2, assumes X is an
%   interval where the sign of F(X(1)) differs from the sign of F(X(2)).
%   An error occurs if this is not true.  Calling FZERO with an interval  
%   guarantees FZERO will return a value near a point where F changes
%   sign.
%
%   FZERO(F,X), where X is a scalar value, uses X as a starting guess.
%   FZERO looks for an interval containing a sign change for F and
%   containing X.  If no such interval is found, NaN is returned.  
%   In this case, the search terminates when the search interval
%   is expanded until an Inf, NaN, or complex value is found.
%
%   FZERO(F,X,TOL) sets the relative tolerance for the convergence test.  
%   FZERO(F,X,TOL,TRACE) displays information at each iteration when
%   TRACE is nonzero.
%   FZERO(F,X,TOL,TRACE,P1,P2,...) allows for additional arguments
%   which are passed to the function, F(X,P1,P2,...).  Pass an empty
%   matrix for TOL or TRACE to use the default value.
%
%   Examples
%       fzero('sin', 3) returns pi. Note the quotes around sin.  
%       Ordinarily, functions are defined in M-files.
%       fzero('abs(x)+1', 1) returns NaN since this function does
%       not change sign anywhere on the real axis (and does not have
%       a zero as well).
%       fzero('sin', 3, [], 1) returns pi, uses the default tolerance,
%       and displays iteration information.
%
%   See also ROOTS.

%   Copyright (c) 1984-98 by The MathWorks, Inc.
%   $Revision: 5.12 $  $Date: 1997/11/21 23:30:46 $

%  This algorithm was originated by T. Dekker.  An Algol 60 version,
%  with some improvements, is given by Richard Brent in "Algorithms for
%  Minimization Without Derivatives", Prentice-Hall, 1973.  A Fortran
%  version is in Forsythe, Malcolm and Moler, "Computer Methods
%  for Mathematical Computations", Prentice-Hall, 1976.

% Initialization

if nargin < 3 | isempty(tol), tol = eps; end
if nargin < 4 | isempty(trace), trace = 0; end
if trace
  header = ' Func evals      x            f(x)          Procedure';
  step=' ';
  count = 0;
end
if  (~isfinite(x))
   error('Second argument must be finite.')
end

% Convert to inline function as needed.
FunFcn = fcnchk(FunFcn,length(varargin));

% Interval input
if (length(x) == 2)
  a = x(1);
  b = x(2);
  fa = feval(FunFcn,a,varargin{:});
  fb = feval(FunFcn,b,varargin{:});
  if any(~isfinite([fa fb])) | any(~isreal([fa fb]))
     error('Function values at interval endpoints must be finite and real.')
  end
  if trace
    disp(header)
    data = [a fa]; step='       initial';
    count = count + 1;
    disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
    data = [b fb]; step = '       initial';
    count = count + 1;   
    disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
  end
  if (fa > 0) == (fb > 0)
    error('The function values at the interval endpoints must differ in sign.')
  end

% Starting guess scalar input
elseif (length(x) == 1)
  fx = feval(FunFcn,x,varargin{:});
  if fx == 0
    b = x;
    return
  elseif ~isfinite(fx) | ~isreal(fx)
    error('Function value at starting guess must be finite and real.');
  end
  if trace
     disp(header)
     data = [x fx]; step='       initial';
     count = count + 1;     
     disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
  end
  if x ~= 0,
    dx = x/50;
  else,
    dx = 1/50;
  end

  % Find change of sign.
  twosqrt = sqrt(2);
  a = x; fa = fx; b = x; fb = fx;
  
  while (fa > 0) == (fb > 0)
     dx = twosqrt*dx;
     a = x - dx;  fa = feval(FunFcn,a,varargin{:});
     if ~isfinite(fa) | ~isreal(fa)
       disperr(a,fa);
       b = NaN;
       return
     end
     if trace
        data = [a fa];  step='       search';
        count = count + 1;
        disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
     end
     if (fa > 0) ~= (fb > 0)
        break
     end
     b = x + dx;  fb = feval(FunFcn,b,varargin{:});
     if ~isfinite(fb) | ~isreal(fb)
       disperr(b,fb);
       b = NaN;
       return
     end
     if trace
        data = [b fb];  step='       search';
        count = count + 1;        
        disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
     end
   end % while
   if trace
     disp(' ')
     disp(['   Looking for a zero in the interval [', ...
                 num2str(a) , ', ', num2str(b), ']']);
     disp(' ')
   end
else
   error('Second argument must be of length 1 or 2.');
end % if (length(x) == 2

fc = fb;
% Main loop, exit from middle of the loop
while fb ~= 0
   % Insure that b is the best result so far, a is the previous
   % value of b, and c is on the opposite of the zero from b.
   if (fb > 0) == (fc > 0)
      c = a;  fc = fa;
      d = b - a;  e = d;
   end
   if abs(fc) < abs(fb)
      a = b;    b = c;    c = a;
      fa = fb;  fb = fc;  fc = fa;
   end

   % Convergence test and possible exit
   m = 0.5*(c - b);
   toler = 2.0*tol*max(abs(b),1.0);
   if (abs(m) <= toler) + (fb == 0.0), break, end

   % Choose bisection or interpolation
   if (abs(e) < toler) + (abs(fa) <= abs(fb))
   % Bisection
      d = m;  e = m;
      step='       bisection';
   else
   % Interpolation
      s = fb/fa;
      if (a == c)
      % Linear interpolation
         p = 2.0*m*s;
         q = 1.0 - s;
      else
      % Inverse quadratic interpolation
         q = fa/fc;
         r = fb/fc;
         p = s*(2.0*m*q*(q - r) - (b - a)*(r - 1.0));
         q = (q - 1.0)*(r - 1.0)*(s - 1.0);
      end;
      if p > 0, q = -q; else p = -p; end;
      % Is interpolated point acceptable
      if (2.0*p < 3.0*m*q - abs(toler*q)) * (p < abs(0.5*e*q))
         e = d;  d = p/q;
         step='       interpolation';
      else
         d = m;  e = m;
         step='       bisection';
      end;
   end % Interpolation

   % Next point
   a = b;
   fa = fb;
   if abs(d) > toler, b = b + d;
   else if b > c, b = b - toler;
        else b = b + toler;
        end
   end
   fb = feval(FunFcn,b,varargin{:});
   if trace
      data = [b fb];  
      count = count + 1;      
      disp([sprintf('%5.0f   %13.6g %13.6g ',count, data), step])
   end
end % Main loop


%------------------------------------------------------------------

function disperr(y, fy)
%DISPERR Display an appropriate error message when FY is Inf,
%   NaN, or complex.  Assumes Y is the value and FY is the function
%   value at Y. If FY is neither Inf, NaN, or complex, it generates
%   an error message.

if ~isfinite(fy)  % NaN or Inf detected
       disp('NaN or Inf function value encountered during ');
       disp('   search for an interval containing a sign change.');
       disp(['Function value at ', num2str(y),' is ',num2str(fy)]);
       disp('Aborting since no such interval was found.')
       disp('Check function or try again with a different starting value.')
elseif ~isreal(fy) % Complex value detected
       disp('Complex function value encountered during ');
       disp('   search for an interval containing a sign change.');
       disp(['Function value at ', num2str(y),' is ',num2str(fy)]);
       disp('Aborting since no such interval was found.')
       disp('Check function or try again with a different starting value.')
else
       error('Disperr called with invalid argument.')
end


http://www.mathworks.com/support/solutions/data/1-179SF.html?product=OP&solution=1-179SF

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-11-19 12:20 , Processed in 0.062922 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表