610 likes | 825 Views
MATLAB 程序设计基础. 程序设计. M 文件 两种形式:命令形式( Script ) 函数形式( Function ) 命令式 M 文件在运行过程中可以调用 MATLAB 工作域内所有的数据,而且,所产生的所有变量均为全局变量,直到用户执行 clear 命令清除;函数式文件中所有变量除特殊声明,均为局部变量。. 命令式 M 文件 提示: 标点符号要运用恰当; 注意程序的书写风格,保持程序的可读性; 要以 m 为文件扩展名,在低版本的 matlab 中,文件名要符合 8.3 格式。.
E N D
MATLAB程序设计基础 程序设计
M文件 两种形式:命令形式(Script) 函数形式(Function) 命令式M文件在运行过程中可以调用MATLAB工作域内所有的数据,而且,所产生的所有变量均为全局变量,直到用户执行clear命令清除;函数式文件中所有变量除特殊声明,均为局部变量。
命令式M文件 提示: • 标点符号要运用恰当; • 注意程序的书写风格,保持程序的可读性; • 要以m为文件扩展名,在低版本的matlab中,文件名要符合8.3格式。
函数式M文件 function [返回变量列表]=函数名(输入变量列表) 注释说明语句段 函数体 提示: • 第一行为function语句; • function后定义函数名和输入输出参数,函数被调用时按此格式执行; • 文件名必须与函数名一一对应; • 函数执行完后,只保留返回结果,不保留中间过程;
例: function f=fibfun(n) %FIBFUN for calculating fibonacci numbers. %Incidengtally, the name fibonacci comes from %Filius Bonassi, or "son of Bonassus" %fibfun.m if n>2 f=fibfun(n-1)+fibfun(n-2); else f=1; end
?help fibfun FIBFUN for calculating fibonacci numbers. Incidengtally, the name fibonacci comes from Filius Bonassi, or "son of Bonassus" fibfun.m ?lookfor fib FIBFUN for calculating fibonacci numbers. 注:为了利用MATLAB的关键字搜索功能,应该在M文件的第一行注释中,尽可能多的包含函数的特征信息。
控制语句 • 循环语句 有两种方式:for循环和while循环 • for循环 for 循环变量=s1:s3:s2 循环体语句组 end 说明: • for 语句一定要有end结束标志; • 循环语句中要用“;”防止中间结果的输出; • 书写时采用锯齿结构以增加可读性;
例:求 mysum=0; for i=1:1:100 mysum=mysum+i; end; mysum 求取s1的值->i i在s1和s2之间? 否 结束循环 是 循环体语句组 i+s3->i
for 循环的一般形式 for v=vect statements end vect为任意给定的向量,则循环变量从向量的第一个数值一直循环到最后一个数值。 例1(见前例): mysum=0; v=1:100; for i=v;mysum=mysum+i;end mysum 例2: x=[]; for i='Hello', x=[i x]; end, x
while循环 while 逻辑变量 循环体语句组 end 例(见前例): mysum=0;i=1; while (i<=100) mysum=mysum+i; i=i+1; end mysum 条件为真? 否 结束 循环 是 循环体语句
条件转移结构 if 逻辑变量 条件语句组 end 例: mysum=0; for m=1:1000 if (mysum>10000), break; end mysum=mysum+m; end [m, mysum]
if 条件式 条件块语句组1 else 条件块语句组2 end 否 是 条件语句组 语句组1 语句组2
例:多项式加 p1=[1 5 4]; p2=[1 6 11 6]; n1=length(p1); n2=length(p2); if n1<n2, p1=[zeros(1,n2-n1) p1]; else p2=[zeros(1,n1-n2) p2]; end psum=p1+p2 psum = 1 7 16 10
if 条件式1 条件块语句组1 elseif 条件式2 条件块语句组2 … else 条件块语句组n+1 end 否 条件1 否 条件2 是 否 条件n 是 是 语句组1 语句组2 语句组n 语句组n+1
分支语句 switch 开关表达式 case 表达式1 语句段1 case {表达式2,表达式3,…,表达式m} 语句段2 … otherwise 语句段n end
注意: • 无需像C语言那样在下一个case语句前加break语句; • 当需要在开关表达式满足若干个表达式之一时,用单元结构来表示; • otherwise等价于C语言的default语句; • 程序的执行结果与case语句的次序无关。
试探式语句 try 语句段1 catch 语句段2 end 首先试探性的执行语句段1,如果在执行过程中出现错误,则将错误信息赋给lasterr变量,并放弃该段语句,转而执行语句段2中的语句。
function c=testtry(a,b) try c=a+b; catch c=strcat(a,b); end
人机交互语句 • echo语句 echo on 打开命令式文件的回应命令; echo off 关闭回应命令; echo file on 使file文件的命令在执行中被显示; echo file off 关闭file文件的命令执行中的回应; echo on all 显示所有执行文件的执行过程; echo off all 关闭所有执行文件的回应显示;
用户输入提示命令 input 用来提示用户从键盘输入数据、字符串或表达式,并接收输入值。 ?r=input('What''s your name?','s') What's your name?Gundam r = Gundam ?r=input('How many apples:') How many apples:2 r = 2
yesinput 智能输入命令 answer=yesinput(question,default,possib) question为屏幕提示问题,default为默认值,possib为检验范围。
keyboard 暂停执行程序并等待键盘输入状态,处理完毕后,键入return并回车,程序将继续运行,通常用来对程序调试及在程序中修改变量。 • pause pause 暂停程序,等待回应; pause(n) 等待n秒后继续执行; pause on 显示并执行pause命令; pause off 显示但不执行pause命令。
中断命令 break 用在循环语句或条件语句中,使得不必等待循环的自然结束。 例:鸡兔同笼,头有36, 脚共100,求鸡兔各多少? i=1; while i if rem(100-i*2,4)==0&(i+(100-i*2)/4)==36 break; end i=i+1; end chicken=i rabit=(100-2*i)/4
函数变量 • nargin 函数输入变量的个数 例:编制函数test1实现如下功能:如果只提供一个输入变量,则求该输入变量的模,如果有两个输入变量则求它们的和。 function c=test1(a,b) if(nargin==1) c=det(a); elseif (nargin==2) c=a+b; end
varargin 可以实现不定数目的输入变量的函数,函数的一切输入变量均存储在单元数组varargin中。 • 与之相对应,输出变量也有相应的函数,如:nargout、varargout等。
变量作用域 • 函数内部定义的变量均为局部变量,如果需要使用全局变量,则应当使用命令global定义,并且在任何使用该全局变量的函数中都应加以定义。 • 定义全局变量时,变量之间必须用空格分隔,不能以逗号分隔。
function [num1,num2,num3]=test3(varargin) global firstlevel secondlevel num1=0;num2=0;num3=0; list=zeros(nargin); for i=1:nargin list(i)=sum(varargin{i}(:)); list(i)=list(i)/length(varargin{i}); if list(i)>firstlevel num1=num1+1; elseif list(i)>secondlevel num2=num2+1; else num3=num3+1; end end ?global firstlevel secondlevel ?firstlevel=85; ?secondlevel=75; ?[a,b,c]=test3([90,89,60],[79,89,60],[99,98,100]) a = 1 b = 2 c = 0
子函数与局部函数 • 函数文件中题头定义的函数为主函数,在函数体内定义的其他函数即为子函数。子函数只能为主函数或同一主函数下其他的子函数所调用。 function c=test(a,b) %main function c=test1(a,b)*test2(a,b); function c=test1(a,b) %sub function c=a+b; function c=test2(a,b) %sub function c=a-b;
放置于目录private下的函数称为局部函数,这些函数只有private目录的父目录中的函数才可以调用,其他目录的函数不能调用。局部函数与一般函数文件的编辑相同。放置于目录private下的函数称为局部函数,这些函数只有private目录的父目录中的函数才可以调用,其他目录的函数不能调用。局部函数与一般函数文件的编辑相同。 • MATLAB在调用函数时,首先检测该函数是否为此文件的子函数;如果不是,再检测是否为可用的局部函数;如果仍不是,则检测MATLAB搜索路径中其他的M文件。
程序设计的辅助函数 • 执行函数 [y1,y2,…,yn]=feval(function,x1,x2,…,xn) 以函数名为输入变量的函数。 evalin(workspacename,’expression’) 对指定工作空间workspacename中的变量进行操作,计算表达式expression的值。
容错函数 error(‘错误信息’) 触发函数error时,中断程序的运行,显示错误信息。 warning用法类似, 但不会中断程序。 function c=testerror(a,b) flag=0; if ischar(a)&ischar(b) flag=1; else error('Input must be a string!'); end if flag c=strcat(a,b); end
时间控制函数 日期表达形式: dd-mmm-yyyy mm/dd/yy mm/dd 12-Oct-2003 10/12/03 10/12 时间表达形式: HH:MM:SS HH:MM:SS PM
cputime的调用: t=cputime; 程序段; t=cputime-t; 显示该程序段运行所占用的CPU时间。
tic、toc的调用方法 tic; 程序段; toc; 显示运行该程序段所需的时间。 • etime(time2,time1) 计算两时刻的时间差。
程序设计优化 • 以矩阵为操作主体 以向量运算代替循环运算,提倡矩阵操作 ?tic;x=1;for i=1:1000,y(i)=sin(x);x=x+0.1*pi;end,toc elapsed_time = 0.0500 ?tic;x=1:0.1*pi:1000*pi;y=sin(x);toc elapsed_time = 0.0100
在多重循环的情况下,建议外循环执行循环次数少的,内循环执行循环次数多的。在多重循环的情况下,建议外循环执行循环次数少的,内循环执行循环次数多的。 例:生成5×10000的Hilbert矩阵,其中 hi,j=1/(i+j-1) ?test1 elapsed_time = 0.2970 ?test2 elapsed_time = 0.6100 Test1.m tic for i=1:5 for j=1:10000 H(i,j)=1/(i+j-1); end end toc Test2.m tic for j=1:10000 for i=1:5 H(i,j)=1/(i+j-1); end end toc
大型矩阵预先定维 大型矩阵动态的定维会降低程序运行效率,所以,应预先估计变量的最大维数,用zeros或ones等进行预先定维。 tic H=zeros(5,10000); for i=1:5 for j=1:10000 H(i,j)=1/(i+j-1); end end toc tic H=zeros(5,10000); for i=1:5 H(i,:)=1./[i:i+9999]; end toc ?test1 elapsed_time = 0.2970 ?test2 elapsed_time = 0.0310
对于二重循环,还可以使用meshgrid函数来构造。对于二重循环,还可以使用meshgrid函数来构造。 • 优先考虑内在函数 • 采用有效算法 • 采用Mex技术 ?tic,[i,j]=meshgrid(1:5,1:10000);H=1./(i+j-1);toc elapsed_time = 0.0150
面向对象的程序设计 • 类和对象的构造 类的概念是结构体的拓展,类中可以包含变量形成员,也可以包含与这些变量相关联的函数或运算。对象是类的一个实例。 • 首先定义一个适当的名字; • 以这个名字建立一个子目录,目录名为该名称前加@符号; • 编写一个引导函数,函数名与类同名。
例:定义一个多项式类 • 如果不给出输入变量,则建立一个空多项式; • 如果输入变量a为多项式类,则直接把它传送给输出变量p; • 如果a为向量,则将此向量变换成行向量,再构造一个多项式对象; function p=polynom(a) if nargin==0 p.c=[];p=class(p,'polynom'); elseif isa(a,'polynom'), p=a; else p.c=a(:).';p=class(p,'polynom'); end
function s=char(p) if all(p.c==0) s='0'; else d=length(p.c)-1;s=[]; for a=p.c; if a~=0 if ~isempty(s) if a>0, s=[s,'+']; else, s=[s,'-'];a=-a; end end if a~=1|d==0, s=[s, num2str(a)]; if d>0, s=[s,'*']; end end if d>=2, s=[s,'x^',int2str(d)]; elseif d==1, s=[s 'x']; end end d=d-1; end end • 类的显示 在此目录下重新建立display()函数。 函数自动按照多项式显示的格式构造字符串,并显示出来。 function display(p) disp(' ');disp([inputname(1),' = ']) disp(' ');disp([' ' char(p)]);disp(' ');
各种运算的建立 加法运算:对plus()函数进行重载定义; 减法运算:对minus()函数进行重载定义; 乘法运算:对mtimes()函数进行重载定义; 乘方运算:对mpower()函数进行重载定义;
function p=mpower(a,n) if n>=0, n=floor(n);a=polynom(a);p=1; if n>=1 for i=1:n, p=p*a;end end else error('Power should be a non-negative integer.') end function p=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]); function p=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]); function p=mtimes(a,b) a=polynom(a); b=polynom(b); p=polynom(conv(a.c,b.c));
?P=polynom([1 4 0 -7]) P = x^3+4*x^2-7 ?Q=polynom([5 3 -1.5 7 8]) Q = 5*x^4+3*x^3-1.5*x^2+7*x+8 ?P+Q ans = -5*x^4-2*x^3+5.5*x^2-7*x-15 ?P-Q ans = -5*x^4-2*x^3+5.5*x^2-7*x-15 ?P*Q ans = 5*x^7+23*x^6+10.5*x^5-34*x^4+15*x^3+42.5*x^2-49*x-56 ?P^3 ans = 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;变量列表为要存储的变量,各个变量名间用空格分割,如果不给出变量名列表,则将整个工作空间中所有变量都存入该文件。
例: save tmp a b c 将a,b,c三个变量存到tmp.mat文件中,默认目录为work目录。 save(‘temp space’,’a’,’b’,’c’) 可以使用任意的合法文件名。
变量装载命令 load 文件名 或 load(文件名) 从mat文件中将变量数据装载入工作空间。 • ASCII格式的变量存储 save temp.dat /ascii 此时,文件内容为可读的,当变量的精度被降低。
文件操作函数 • 打开文件 文件句柄=fopen(‘文件名’,’打开方式‘) 如果句柄的值大于0,说明文件打开成功;打开方式: r - 只读 w - 只写 a - 追加 r+ - 可读又可写 …
关闭文件 fclose(文件句柄) 成功,则返回0;否则返回-1。 如果想关闭matlab运行中打开的所有文件,可以用fclose(‘all’)命令。 • 有格式读文件 A=fscanf(文件句柄,’输入格式’,变量大小N) 从文件中读取N个元素,赋给A。