资源描述:
《MATLAB第六讲》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
MATLAB程序设计基础程序设计 M文件两种形式:命令形式(Script)函数形式(Function)命令式M文件在运行过程中可以调用MATLAB工作域内所有的数据,而且,所产生的所有变量均为全局变量,直到用户执行clear命令清除;函数式文件中所有变量除特殊声明,均为局部变量。 命令式M文件提示:标点符号要运用恰当;注意程序的书写风格,保持程序的可读性;要以m为文件扩展名,在低版本的matlab中,文件名要符合8.3格式。 函数式M文件function[返回变量列表]=函数名(输入变量列表)注释说明语句段函数体提示:第一行为function语句;function后定义函数名和输入输出参数,函数被调用时按此格式执行;文件名必须与函数名一一对应;函数执行完后,只保留返回结果,不保留中间过程; 例:functionf=fibfun(n)%FIBFUNforcalculatingfibonaccinumbers.%Incidengtally,thenamefibonaccicomesfrom%FiliusBonassi,or"sonofBonassus"%fibfun.mifn>2f=fibfun(n-1)+fibfun(n-2);elsef=1;end ?helpfibfunFIBFUNforcalculatingfibonaccinumbers.Incidengtally,thenamefibonaccicomesfromFiliusBonassi,or"sonofBonassus"fibfun.m?lookforfibFIBFUNforcalculatingfibonaccinumbers.注:为了利用MATLAB的关键字搜索功能,应该在M文件的第一行注释中,尽可能多的包含函数的特征信息。 控制语句循环语句有两种方式:for循环和while循环for循环for循环变量=s1:s3:s2循环体语句组end说明:for语句一定要有end结束标志;循环语句中要用“;”防止中间结果的输出;书写时采用锯齿结构以增加可读性; 例:求mysum=0;fori=1:1:100mysum=mysum+i;end;mysum求取s1的值->ii在s1和s2之间?循环体语句组i+s3->i是否结束循环 for循环的一般形式forv=vectstatementsendvect为任意给定的向量,则循环变量从向量的第一个数值一直循环到最后一个数值。例1(见前例):mysum=0;v=1:100;fori=v;mysum=mysum+i;endmysum例2:x=[];fori='Hello',x=[ix];end,x while循环while逻辑变量循环体语句组end例(见前例):mysum=0;i=1;while(i<=100)mysum=mysum+i;i=i+1;endmysum条件为真?循环体语句是否结束循环 条件转移结构if逻辑变量条件语句组end例:mysum=0;form=1:1000if(mysum>10000),break;endmysum=mysum+m;end[m,mysum] if条件式条件块语句组1else条件块语句组2end条件语句组语句组1语句组2是否 例:多项式加p1=[154];p2=[16116];n1=length(p1);n2=length(p2);ifn1firstlevelnum1=num1+1;elseiflist(i)>secondlevelnum2=num2+1;elsenum3=num3+1;endend?globalfirstlevelsecondlevel?firstlevel=85;?secondlevel=75;?[a,b,c]=test3([90,89,60],[79,89,60],[99,98,100])a=1b=2c=0 子函数与局部函数函数文件中题头定义的函数为主函数,在函数体内定义的其他函数即为子函数。子函数只能为主函数或同一主函数下其他的子函数所调用。functionc=test(a,b)%mainfunctionc=test1(a,b)*test2(a,b);functionc=test1(a,b)%subfunctionc=a+b;functionc=test2(a,b)%subfunctionc=a-b; 放置于目录private下的函数称为局部函数,这些函数只有private目录的父目录中的函数才可以调用,其他目录的函数不能调用。局部函数与一般函数文件的编辑相同。MATLAB在调用函数时,首先检测该函数是否为此文件的子函数;如果不是,再检测是否为可用的局部函数;如果仍不是,则检测MATLAB搜索路径中其他的M文件。 程序设计的辅助函数执行函数[y1,y2,…,yn]=feval(function,x1,x2,…,xn)以函数名为输入变量的函数。evalin(workspacename,’expression’)对指定工作空间workspacename中的变量进行操作,计算表达式expression的值。 容错函数error(‘错误信息’)触发函数error时,中断程序的运行,显示错误信息。warning用法类似,但不会中断程序。functionc=testerror(a,b)flag=0;ifischar(a)&ischar(b)flag=1;elseerror('Inputmustbeastring!');endifflagc=strcat(a,b);end 时间控制函数日期表达形式:dd-mmm-yyyymm/dd/yymm/dd12-Oct-200310/12/0310/12时间表达形式:HH:MM:SSHH:MM:SSPM cputime的调用:t=cputime;程序段;t=cputime-t;显示该程序段运行所占用的CPU时间。 tic、toc的调用方法tic;程序段;toc;显示运行该程序段所需的时间。etime(time2,time1)计算两时刻的时间差。 程序设计优化以矩阵为操作主体以向量运算代替循环运算,提倡矩阵操作?tic;x=1;fori=1:1000,y(i)=sin(x);x=x+0.1*pi;end,tocelapsed_time=0.0500?tic;x=1:0.1*pi:1000*pi;y=sin(x);tocelapsed_time=0.0100 在多重循环的情况下,建议外循环执行循环次数少的,内循环执行循环次数多的。例:生成5×10000的Hilbert矩阵,其中hi,j=1/(i+j-1)Test2.mticforj=1:10000fori=1:5H(i,j)=1/(i+j-1);endendtocTest1.mticfori=1:5forj=1:10000H(i,j)=1/(i+j-1);endendtoc?test1elapsed_time=0.2970?test2elapsed_time=0.6100 大型矩阵预先定维大型矩阵动态的定维会降低程序运行效率,所以,应预先估计变量的最大维数,用zeros或ones等进行预先定维。ticH=zeros(5,10000);fori=1:5forj=1:10000H(i,j)=1/(i+j-1);endendtocticH=zeros(5,10000);fori=1:5H(i,:)=1./[i:i+9999];endtoc?test1elapsed_time=0.2970?test2elapsed_time=0.0310 对于二重循环,还可以使用meshgrid函数来构造。优先考虑内在函数采用有效算法采用Mex技术?tic,[i,j]=meshgrid(1:5,1:10000);H=1./(i+j-1);tocelapsed_time=0.0150 面向对象的程序设计类和对象的构造类的概念是结构体的拓展,类中可以包含变量形成员,也可以包含与这些变量相关联的函数或运算。对象是类的一个实例。首先定义一个适当的名字;以这个名字建立一个子目录,目录名为该名称前加@符号;编写一个引导函数,函数名与类同名。 例:定义一个多项式类如果不给出输入变量,则建立一个空多项式;如果输入变量a为多项式类,则直接把它传送给输出变量p;如果a为向量,则将此向量变换成行向量,再构造一个多项式对象;functionp=polynom(a)ifnargin==0p.c=[];p=class(p,'polynom');elseifisa(a,'polynom'),p=a;elsep.c=a(:).';p=class(p,'polynom');end 类的显示在此目录下重新建立display()函数。函数自动按照多项式显示的格式构造字符串,并显示出来。functiondisplay(p)disp('');disp([inputname(1),'='])disp('');disp([''char(p)]);disp('');functions=char(p)ifall(p.c==0)s='0';elsed=length(p.c)-1;s=[];fora=p.c;ifa~=0if~isempty(s)ifa>0,s=[s,'+'];else,s=[s,'-'];a=-a;endendifa~=1|d==0,s=[s,num2str(a)];ifd>0,s=[s,'*'];endendifd>=2,s=[s,'x^',int2str(d)];elseifd==1,s=[s'x'];endendd=d-1;endend 各种运算的建立加法运算:对plus()函数进行重载定义;减法运算:对minus()函数进行重载定义;乘法运算:对mtimes()函数进行重载定义;乘方运算:对mpower()函数进行重载定义; functionp=minus(a,b)a=polynom(a);b=polynom(b);k=length(b.c)-length(a.c);p=polynom([zeros(1,k)a.c]-[zeros(1,-k)b.c]);functionp=minus(a,b)a=polynom(a);b=polynom(b);k=length(b.c)-length(a.c);p=polynom([zeros(1,k)a.c]-[zeros(1,-k)b.c]);functionp=mtimes(a,b)a=polynom(a);b=polynom(b);p=polynom(conv(a.c,b.c));functionp=mpower(a,n)ifn>=0,n=floor(n);a=polynom(a);p=1;ifn>=1fori=1:n,p=p*a;endendelseerror('Powershouldbeanon-negativeinteger.')end ?P=polynom([140-7])P=x^3+4*x^2-7?Q=polynom([53-1.578])Q=5*x^4+3*x^3-1.5*x^2+7*x+8?P+Qans=-5*x^4-2*x^3+5.5*x^2-7*x-15?P-Qans=-5*x^4-2*x^3+5.5*x^2-7*x-15?P*Qans=5*x^7+23*x^6+10.5*x^5-34*x^4+15*x^3+42.5*x^2-49*x-56?P^3ans=x^9+12*x^8+48*x^7+43*x^6-168*x^5-336*x^4+147*x^3+588*x^2-343 文件格式与读写Matlab的文件MDL文件-simulink生成的模型描述文件;DLL文件-由Mex技术生成的matlab可调用函数库;MAT文件-matlab格式存储的二进制数据文件P文件-M文件变换后的伪代码文件。 变量存储命令save文件名变量列表文件名为要存储的文件名,如果不给出文件名则默认为matlab.mat;变量列表为要存储的变量,各个变量名间用空格分割,如果不给出变量名列表,则将整个工作空间中所有变量都存入该文件。 例:savetmpabc将a,b,c三个变量存到tmp.mat文件中,默认目录为work目录。save(‘tempspace’,’a’,’b’,’c’)可以使用任意的合法文件名。 变量装载命令load文件名或load(文件名)从mat文件中将变量数据装载入工作空间。ASCII格式的变量存储savetemp.dat/ascii此时,文件内容为可读的,当变量的精度被降低。 文件操作函数打开文件文件句柄=fopen(‘文件名’,’打开方式‘)如果句柄的值大于0,说明文件打开成功;打开方式:r-只读w-只写a-追加r+-可读又可写… 关闭文件fclose(文件句柄)成功,则返回0;否则返回-1。如果想关闭matlab运行中打开的所有文件,可以用fclose(‘all’)命令。有格式读文件A=fscanf(文件句柄,’输入格式’,变量大小N)从文件中读取N个元素,赋给A。 有格式写文件fprintf(文件句柄,’输出格式’,输出变量表)输出格式控制变量的输出形式,每个描述格式的字符串以%引导,如%s表示字符格式,%d表示整型数格式,%23.13g表示双精度浮点格式;输出变量表中,变量名之间用逗号隔开。 读入整个一行str=fgetl(文件句柄)或str=fgets(文件句柄)从文件中读入一整行信息,前者舍弃字符串末尾的回车符号,后者不舍弃。字符串读写类似于文件读写,把文件句柄替换为字符串变量。sscanf(字符串变量,‘输入格式’,变量大小)字符串变量=sprintf(‘输出格式’,输出变量列表) 例:文本文件显示。functionfileprint(fname)ifnargin==1f_id=eval(['fopen('''fname,'.m'',''r'')']);else[fname,fpath]=uigetfile('*.m','Pleaseenterafilename');f_id=fopen([fpath,fname],'r');endi=0;whilefeof(f_id)==0strText=fgetl(f_id);i=i+1;disp(sprintf('%4d:%s',i,strText));endfclose(f_id); ?fileprint('fileprint')1:functionfileprint(fname)2:ifnargin==13:f_id=eval(['fopen('''fname,'.m'',''r'')']);4:else5:[fname,fpath]=uigetfile('*.m','Pleaseenterafilename');6:f_id=fopen([fpath,fname],'r');7:end8:i=0;9:whilefeof(f_id)==010:strText=fgetl(f_id);11:i=i+1;12:disp(sprintf('%4d:%s',i,strText));13:end14:fclose(f_id); 程序调试语法错误发生在程序代码的解释过程中,一般有函数参数输入类型有误或矩阵运算阶数不符等情况。执行错误发生在程序运行过程中,出现溢出或死循环等引起,错误与程序有关,较难发现。?a=[12;34];?b=[123;456;789];?a*b???Errorusing==>*Innermatrixdimensionsmustagree.?a=NaN?isnan(a)ans=1?a=[];?isempty(a)ans=1尽量避免出现NaN、inf或空矩阵等异常数据,要适当采取方法来控制。 错误检测语法错误会给出相应的信息,容易检查定位;将程序执行的中间结果输出到命令窗口,以方便检查;使用keyboard函数中断程序,进入调试状态,实现交互式调试;将函数头注释掉,从而函数变为脚本文件调试;使用调试菜单或调试函数。 调试函数dbstopinat<行号>用来在M文件中设置断点;函数dbstatus用来显示断点信息;函数dbtype显示M文件文本(包括行号);函数dbstep从断点处继续执行M文件;函数dbstack显示M文件执行时调用的堆栈等;函数dbup/dbdown可以实现工作空间的切换; ?dbtypedb_test1functionC=db_test(A,B)2[num11,num12]=size(A);3[num21,num22]=size(B);4if(num12==num21)5C=A*B6else7if(num11==num22)8C=B*A;9else10error('inputerror!')11end12end13return例:functionC=db_test(A,B)[num11,num12]=size(A);[num21,num22]=size(B);if(num12==num21)C=A*Belseif(num11==num22)C=B*A;elseerror('inputerror!')endendreturn ?dbstopindb_testat5?a=[12;34];?b=[123;456];?db_test(a,b)K?dbstatusBreakpointfore:MATLABR11workdb_testisonline5.K?dbstack>Ine:MATLABR11workdb_test.matline5K?whosNameSizeBytesClassA2x232doublearrayB2x348doublearraynum111x18doublearraynum121x18doublearraynum211x18doublearraynum221x18doublearrayGrandtotalis14elementsusing112bytesK?dbupInbaseworkspace.K?dbquit?