第5章函数5.1函数文件5.2文件的操作5.3INLINE与FEVAL函数5.4MATLAB函数示例§5.1函数文件一、函数文件的基本结构函数文件由function语句引导,其基本结构为:function输出形参表=函数名(输入形参表)注释说明部分函数体语句其中以function开头的一行为引导行,表示该M文件是一个函数文件。函数名的命名规则与变量名相同。输入形参为函数的输入参数,输出形参为函数的输出参数。当输出形参多于一个时,则应该用方括号括起来。例:编写函数文件求半径为r的圆的面积和周长。函数文件如下:function[s,p]=fcircle(r)%CIRCLEcalculatetheareaandperimeterofacircleofradiir%r圆半径%s圆面积%p圆周长s=pi*r*r;p=2*pi*r;函数调用的一般格式是:[输出实参表]=函数名(输入实参表)要注意的是,函数调用时各实参出现的顺序、个数,应与函数定义时形参的顺序、个数一致,否则会出错。函数调用时,先将实参传递给相应的形参,从而实现参数传递,然后再执行函数的功能。二、函数调用例:利用函数文件,实现直角坐标(x,y)与极坐标(ρ,θ)之间的转换。函数文件tran.m:function[rho,theta]=tran(x,y)rho=sqrt(x*x+y*y);theta=atan(y/x);调用tran.m的命令文件main1.m:x=input('Pleaseinputx=:');y=input('Pleaseinputy=:');[rho,the]=tran(x,y);rhothe运行结果:Pleaseinputx=:7Pleaseinputy=:8rho=10.6301the=0.8520在MATLAB中,函数可以嵌套调用,即一个函数可以调用别的函数,甚至调用它自身。一个函数调用它自身称为函数的递归调用。例:利用函数的递归调用,求n!。n!本身就是以递归的形式定义的,显然,求n!需要求(n-1)!,这时可采用递归调用。递归调用函数文件factor.m如下:functionf=factor(n)ifn=1f=1;elsef=factor(n-1)*n;%递归调用求(n-1)!end在调用函数时,MATLAB用两个永久变量nargin和nar-gout分别记录调用该函数时的输入实参和输出实参的个数。只要在函数文件中包含这两个变量,就可以准确地知道该函数文件被调用时的输入输出参数个数,从而决定函数如何进行处理。三、函数参数的可调性例:nargin用法示例。函数文件examp.m:functionfout=examp(a,b,c)ifnargin==1fout=a;elseifnargin==2fout=a+b;elseifnargin==3fout=(a*b*c)/2;end命令文件mydemo.m:x=[1:3];y=[1;2;3];examp(x)examp(x,y')examp(x,y,3)运行结果:ans=123ans=246ans=21在MATLAB中,函数文件是能够创建局部独立空间的程序文件。在函数内定义的所有变量名对函数而言是局部的,既不影响其他程序文件和函数文件中同样的变量名又不被其所影响.所有的MATLAB内置函数都是这种类型。当然在MATLAB中可以定义全局变量。全局变量用global命令定义,格式为:global变量名四、全局变量与局部变量例:全局变量应用示例。先建立函数文件wadd.m,该函数将输入的参数加权相加。functionf=wadd(x,y)globalALPHABETAf=ALPHA*x+BETA*y;在命令窗口中输入:globalALPHABETAALPHA=1;BETA=2;s=wadd(1,2)运算结果:globalALPHABETAALPHA=1;BETA=2;s=wadd(1,2)s=5五、程序调试介绍1、程序调试概述一般来说,应用程序的错误有两类,一类是语法错误,另一类是运行时的错误。语法错误包括词法或文法的错误,例如函数名的拼写错、表达式书写错等。程序运行时的错误是指程序的运行结果有错误,这类错误也称为程序逻辑错误。2、调试器①Debug菜单项菜单项用于程序调试,需要与Breakpoints菜单项配合使用。②Breakpoints菜单项该菜单项共有6个菜单命令,前两个是用于在程序中设置和清除断点的,后4个是设置停止条件的,用于临时停止M文件的执行,并给用户一个检查局部变量的机会,相当于在M文件指定的行号前加入了一个keyboard命令。除了采用调试器调试程序外,MATLAB还提供了一些命令用于程序调试。命令的功能和调试器菜单命令类似,具体使用方法请读者查询MATLAB帮助文档。六、调试命令§5.2文件的操作fopen函数的调用格式为:fid=fopen(文件名,打开方式)其中文件名用字符串形式,表示待打开的数据文件。常见的打开方式有:‘r’表示对打开的文件读数据,‘w’表示对打开的文件写数据,‘a’表示在打开的文件末尾添加数据。fid用于存储文件句柄值,句柄值用来标识该数据文件,其他函数可以利用它对该数据文件进行操作。一、文件的打开与关闭1、文件的打开文件数据格式有两种形式,一是二进制文件,二是文本文件。在打开文件时需要进一步指定文件格式类型,即指定是二进制文件还是文本文件。文件在进行完读、写等操作后,应及时关闭。关闭文件用fclose函数,调用格式为:sta=fclose(fid)该函数关闭fid所表示的文件。sta表示关闭文件操作的返回代码,若关闭成功,返回0,否则返回–1。2、文件的关闭二、文件的读写操作fread函数可以读取二进制文件的数据,并将数据存入矩阵。其调用格式为:[A,COUNT]=fread(fid,size,precision)其中A用于存放读取的数据,COUNT返回所读取的数据元素个数,fid为文件句柄,size为可选项,若不选用则读取整个文件内容,若选用则它的值可以是下列值:(1)N表示读取N个元素到一个列向量。(2)Inf表示读取整个文件。(3)[M,N]表示读数据到M×N的矩阵中,数据按列存放。precision代表读写数据的类型1、二进制文件的读写操作读二进制文件fwrite函数按照指定的数据类型将矩阵中的元素写入到文件中。其调用格式为:COUNT=fwrite(fid,A,precision)其中COUNT返回所写的数据元素个数,fid为文件句柄,A用来存放写入文件的数据,precision用于控制所写数据的类型,其形式与fread函数相同。写二进制文件例:建立一数据文件magic5.dat,用于存放5阶魔方阵。程序如下:fid=fopen(‘magic5.dat’,‘w’);cnt=fwrite(fid,magic(5),‘int32’);fclose(fid);运行结果:2、文本文件的读写操作fscanf函数的调用格式为:[A,COUNT]=fscanf(fid,format,size)其中A用以存放读取的数据,COUNT返回所读取的数据元素个数。fid为文件句柄。format用以控制读取的数据格式,由%加上格式符组成,常见的格式符有d,f,c,s。size为可选项,决定矩阵A中数据的排列形式。读文本文件写文本文件fprintf函数的调用格式为:COUNT=fprintf(fid,format,A)其中A存放要写入文件的数据。先按format指定的格式将数据矩阵A格式化,然后写入到fid所指定的文件。格式符与fscanf函数相同。例:建立一个文本文件并写入数据x=0:0.1:1;y=[x;exp(x)];fn=fopen('exp.txt','w');fprintf(fn,'%6.2f%12.8f\n',y)fclose(fn);typeexp.txtexp.txt的位置三、INLINE与FEVAL函数在MATLAB命令窗口,程序或函数中创建局部函数时,可以使用inline.优点是它不必存储为一单独文件。调用inline函数的一般形式为:FuctionName=inline(’expression’,’p1’,’p2’,…)其中,expression本身是任何有效的MATLAB表达式,p1,p2,…是出现在expression中的所有变量的名字。1、INLINE函数Inline使用限制:①它不能调用另一个inline函数.②它只能由一个MATLAB表达式组成,并且它只能返回一个变量。例:用inline函数创建一个函数FofX求解下式:f(x)=x*x*cos(ax)-b其中a和b是标量。则有在命令窗口中输入:FofX=inline('x.^2.*cos(a*x)-b','x','a','b')当在命令窗口中输入如下表达式时:g=FofX([pi/3pi/3.5],4,1)系统输出:g=-1.5483-1.72592、FEVAL函数Feval是函数的函数,有许多MATLAB内置函数要求用户通过它们创建特定形式的用户自定义函数.使用feval的MATLAB函数主要有:fzero---找f(x)=0的根roots---找一多项式的根quad8---在给定间隔内对f(x)的数值积分trapz---在给定间隔内对f(x)的数值积分polyarea---决定一闭合曲线内的面积fminbnd---在一特定间隔内找到f(x)的局部最小值ode45---常微分方程组的数值积分fsove---非线性方程组的数值解例:求根程序确定了某函数f(x)=0的m个最接近的根。NoRoots=5Xstart=0.2;Tolerance=1e-6;Increment=0.3;beta=pi/3;a=0.5;c=ManyZeros(‘CosBeta’,NoRoots,xstart,tolerance,increment,beta,a)functiond=Cosbeta(x,beta,aa)d=cos(x*beta)-aa;求根函数文件ManyZeros:FunctionnRoots=ManyZeros(zname,n,xs,toler,dxx,b,a)x=xs;dx=dxx;Form=1:ns1=sign(feval(zname,x,b,a));Whiledx/xtolerifs1~=sign(feval(zname,x,b,a));dx=dx/2;elsex=x+dxendendnRoots(m)=x;dx=dxx;x=1.05*xend§5.4MATLAB函数示例一、MATLAB解方程与函数极值1、线性方程组求解(1)直接解法①利用左除运算符的直接解法对于线性方程组Ax=b,可以利用左除运算符“\”求解:x=A\b例:用直接解法求解下列线性方程组。命令如下:A=[2,1,-5,1;1,-5,0,7;0,2,1,-1;1,6,-1,-4];b=[13,-9,6,0]';x=A\bx=-66.555625.6667-18.777826.5556矩阵分解是指根据一定的原理用某种算法将一个矩阵分解成若干个矩阵的乘积。常见的矩阵分解有LU分解、QR分解、Cholesky分解,及Schur分解、Hessenberg分解、奇异分解等。②利用矩阵的分解求解线性方程组a.LU分解矩阵的LU分解就是将一个矩阵表示为一个交换下三角矩阵和一个上三角矩阵的乘积形式。线性代数中已经证明,只要方阵A是非奇异的,LU分解总是可以进行的。MATLAB提供的lu函数用于对矩阵进行LU分解,其调用格式为:[L,U]=lu(X):产生一个上三角阵U和一个变换形式的下三角阵L(行交换),使之满足X=LU。注意:这里的矩阵X必须是方阵。[L,U,P]=lu(X):产生一个上三角阵U和一个下三角阵L以及一个置换矩阵P,使之满足PX=LU。当然矩阵X同样必须是方阵。实现LU分解后,线性方程组Ax=b的解x=U\(L\b)或x=U\(L\Pb),这样可以大大提高运算速度。b.QR分解对矩阵X进行QR分解,就是把X分