1、2019年9月6日,第1页,第7章 MATLAB 2007程序设计,MATLAB R2007基础教程 清华大学出版社,教学目标 教学重点 教学内容,2019年9月6日,第2页,教学目标,熟悉 MATLAB 的编程环境 掌握 MATLAB 的变量类型 掌握 MATLAB 中的流程控制语句 掌握 MATLAB 的函数类型和函数操作 了解 MATLAB 中的错误处理 了解 MATLAB 程序调试方法 了解 MATLAB 代码优化方法,2019年9月6日,第3页,教学重点,MATLAB 的编程环境 MATLAB 的变量类型 MATLAB 中的流程控制语句 MATLAB 的函数类型和函数操作MATLAB
2、 程序调试方法,2019年9月6日,第4页,教学内容,M文本文件介绍 函数流程控制 函数变量 函数类型 函数操作 MATLAB 编程错误处理 程序设计的辅助函数 调试程序 优化程序,2019年9月6日,第5页,M文本文件介绍,一个 M 文件通常包含五个部分,函数定义语句、H1 帮助行、帮助文本、函数体或者脚本文件语句和注释语句。H1 行为紧随函数定义语句后面的一行注释语句。当用户通过 help 命令查询该函数的说明信息时 H1 行显示为第一行,另外 lookfor 函数只检索和显示 H1 行。帮助文本为 H1 行后面连续的注释行,当在命令窗口中通过 help 命令查询该函数的说明信息时则在窗口
3、中显示这些内容。函数体为 M 文件的主要部分,是函数的执行代码。除上面的 H1 行和帮助文本外,为了易于理解,可以在书写代码时添加注释语句。这些注释语句在编译程序时会被忽略,因此不会影响编译速度和程序运行速度,但是能够增加程序的可读性。,2019年9月6日,第6页,一个完整的 M 文件的结构为: function f = fact(n) 函数定义语句 % Compute a factorial value. H1 行 % FACT(N) returns the factorial of N, 帮助文本 % usually denoted by N! % Put simply, FACT(N)
4、is PROD(1:N). 注释语句 f = prod(1:n); 函数体 函数定义语句只在函数文件中存在,定义函数名称、输入输出参数的数量和顺序。函数定义语句的格式为: function y = fact(x)。,2019年9月6日,第7页,函数式M文件 函数式 M 文件比脚本式 M 文件相对复杂一些,脚本文件不需要自带参数,也不一定返回结果,而函数文件一般要自带参数,并且有返回结果,以便于更好的把整个程序连为一段。函数文件也可以不带参数,此时文件中一般使用一些全局变量来实现与外界和其他函数之间的数据交换。 函数文件的第一行以 function 开始,说明此文件是一个函数。其实质为用户向 M
5、ATLAB 函数库中添加的子函数。在默认情况下,函数文件中的变量都是局部变量,仅在函数运行期间有效,函数运行结束后,这些变量将从工作区中清除。,2019年9月6日,第8页,函数流程控制,顺序结构 判断语句(ifelseend) 分支语句 循环语句 trycatchend语句 其他流程控制函数,2019年9月6日,第9页,顺序结构,顺序结构是最简单的程序结构,系统在编译程序时,按照程序的物理位置顺序执行。这种程序容易编制,但是结构单一,能够实现的功能有限。,2019年9月6日,第10页,判断语句(ifelseend),ifend ifelseend ifelseifelseend,2019年9月
6、6日,第11页,ifend 此时的程序结构如下: if 表达式执行代码块 end 这是最简单的判断语句,只有一个判断语句,其中的表达式为逻辑表达式,当表达式为真时,执行相应的语句,否则,直接跳到下一段语句。,2019年9月6日,第12页,ifelseend 当程序有两个选择时,可以选择 ifelseend 结构,此时程序结构为: if 表达式执行代码块1 else执行代码块2 end 当判断表达式为真时,执行代码块1,否则执行代码块2。,2019年9月6日,第13页,ifelseifelseend 上面的两种形式中,分别包含一个选择和两个选择,当判断包含多个选择时,可以采用elseif 语句,
7、结构为: if 表达式1执行代码块1 elseif 表达式2执行代码块2 elseif else执行代码块 end 其中可以包含任意多个 elseif 语句。,2019年9月6日,第14页,分支语句,上一节中的 ifelseifelseend 语句可以适用于多种选择的流程控制,此时对 else之外的每一个选择语句设置一个表达式,表达式为真时则执行该模块。MATLAB 中的另一种多选择语句为分支语句。分支语句的结构为: switch 分支语句case 条件语句执行代码块case 条件语句1, 条件语句2, 条件语句3, .执行代码块otherwise执行代码块 end,2019年9月6日,第15
8、页,其中的分支语句为一个变量,可以是数值变量或者字符串变量,如果该变量的值与某一条件相符,则执行相应的语句,否则,执行 otherwise 后面的语句。在每一个条件中,可以包含一个条件语句,可以包含多个条件,当包含多个条件时,将条件以单元数组的形式表示。 MATLAB 的分支语句类似于 C 语言的分支语句,但是又不完全相同:MATLAB 语句从上到下依次判断条件,条件符合则执行相应的代码块,之后退出该分支语句,因此在代码块后面不需要添加“break”语句。,2019年9月6日,第16页,循环语句,for 语句 while 语句,2019年9月6日,第17页,1for 语句,for 语句将相同的
9、代码执行预定义的次数。for 语句的结构为: for 循环变量 = 表达式执行代码块 end for 循环的语句在前面的例子中已经有所涉及,上节的例子中,第二个程序中也涉及到了 for 循环语句。下面为 for 循环的更多例子。,2019年9月6日,第18页,2while 语句,while 语句用于将相同的代码块执行多次,但是次数并不预先指定,当 while 的条件表达式为真时,执行代码块,直到条件表达式为假。while 语句的结构为: while 表达式执行代码块 end,2019年9月6日,第19页,6.2.5 trycatchend语句,MATLAB 中的另一种判断语句为 trycatc
10、h 语句,这种语句可以包容程序运行中的错误,并返回错误类型。这种语句的结构为: try运行代码块 catch 运行代码块 end 该语句首先从上到下依次执行,如果遇到程序错误则运行下一个 catch 中的语句,依次向下进行。如果程序运行成功,则退出该判断语句。如果在 catch 和 end之间的程序运行出错,则程序运行终止,或者如果存在其他的 trycatch 结构,则运行下一个 trycatch 结构。可以利用 lasterr 命令查看发生错误的原因。,2019年9月6日,第20页,6.2.6 其他流程控制函数,continue:continue 语句通常用在循环控制中,包括 for 循环和
11、 while 循环,用于结束当次循环,继续执行下一次循环,但是不结束当前循环。一般 continue 语句与 if 语句相结合,当满足一定的条件时,执行 continue 语句。 break:与 continue 相同的是,break 函数也是用于循环控制,中断当前循环。与 continue 不同,break 跳出当前循环,不再执行该循环的任何操作。 return:结束该程序的执行,返回到调用函数或者键盘。,2019年9月6日,第21页,6.3 函数变量,6.3.1 变量类型 局部变量 全局变量 永久变量,2019年9月6日,第22页,局部变量,每个函数都有自己的局部变量,这些变量存储在该函数
12、独立的工作区中,与其他函数的变量及主工作区中的变量分开存储。当函数调用结束时,这些变量随之删除,不保存在内存中。并且,除了函数返回值,该函数不改变工作区中其他变量的值。 然而脚本文件没有独立的工作区,当通过命令窗口调用脚本文件时,脚本文件分享主工作区,当函数调用脚本文件时,脚本文件分享主调函数的工作区。需要注意的是,如果脚本中改变了工作区中变量的值,则在脚本文件调用结束后,该变量的值发生改变。 在函数中,变量默认为局部变量。,2019年9月6日,第23页,全局变量,局部变量只在一个工作区内有效,无论是函数工作区还是 MATLAB 主工作区。与局部变量不同,全局变量可以在定义该变量的全部工作区中
13、有效。当在一个工作区内改变该变量的值时,该变量在其他工作区中的变量同时改变。 任何函数如果需要使用全局变量,则必须首先声明,声明格式为: global 变量名1 变量名2 如果一个 M 文件中包含的子函数需要访问全局变量,则需在子函数中声明该变量,如果需要在命令行中访问该变量,则需在命令行中声明该变量。,2019年9月6日,第24页,永久变量,除局部变量和全局变量外,MATLAB 中还有一种变量类型为永久变量。永久变量的特点为: 只能在 M 文件内部定义; 只有该变量从属的函数能够访问该变量; 当函数运行结束时,该变量的值保留在内存中,因此当该函数再次被调用时,可以再次利用这些变量。 永久变量
14、的定义方法为: persistent 变量名1 变量名2。,2019年9月6日,第25页,6.4 函数类型,6.4.1 匿名函数 6.4.2 主函数 6.4.3 子函数 6.4.4 嵌套函数 6.4.5 私有函数 6.4.6 重载函数,2019年9月6日,第26页,匿名函数,关于匿名函数在前面“MATLAB 的数学运算”一章中已有初步涉及,在“函数运算”一节的示例中用到了大量的匿名函数。本节对匿名函数做进一步的介绍。 匿名函数提供了一种创建简单程序的方法,使用它用户可以不必每次都编写 M 文件。用户可以在 MATLAB 的命令窗口或是其他任意 M 文件和脚本文件中使用匿名函数。 匿名函数的格式
15、为: fhandle = (arglist) expr 其中 fhandle 是为该函数创建的函数句柄; 符号用于创建函数句柄;arglist 为用逗号分隔的参数列表;expr 为函数主体,为 MATLAB 表达式。,2019年9月6日,第27页,主函数,通常每个 M 文件中的第一个函数为主函数,主函数可以被该文件之外的其他函数调用,而子函数只能被该文件内的函数调用。主函数的调用通过存储该函数的 M 文件的文件名调用。我们在前面几节中编写的实验程序,大多为主函数,如例 6-7。因此,这里不再过多介绍。,2019年9月6日,第28页,子函数,一个 M 文件中可以包括多个函数,除主函数之外的其他函
16、数称为子函数。子函数只能被主函数或该文件内的其他子函数调用。每个子函数以函数定义语句开头,直至下一个函数的定义或文件的结尾。 当函数中调用函数时,系统判断其函数类型的顺序为:首先判断是否为子函数,然后判断是否为私有函数,最后判断其是否为当前目录下的 M 文件函数或者系统内置函数。由于子函数具有最高的优先级别,因此,在定义子函数时,可以采用已有的其他外部函数的名称。,2019年9月6日,第29页,嵌套函数,一个函数内部可以定义其他的函数,这种内部的函数称作嵌套函数。 1嵌套函数的书写 定义嵌套函数时,只要在一个函数内部直接定义嵌套函数即可。需要注意的是当一个 M文件中存在嵌套函数时,该文件内的所
17、有函数必须以 end 结尾。,2019年9月6日,第30页,例 6-14 嵌套函数的结构 function x = A(p1, p2) .function y = B(p3).end . end,2019年9月6日,第31页,每个函数中可以嵌套多个函数。 例 6-15 多个平行嵌套函数 function x = A(p1, p2) .function y = B(p3).endfunction z = C(p4).end . end,2019年9月6日,第32页,在这个程序中,函数 A 嵌套了函数 B 和函数 C。另外,嵌套函数还可以包含嵌套函数,其结构如例 6-16。 例 6-16 多层嵌套
18、函数 function x = A(p1, p2) .function y = B(p3).function z = C(p4).end.end . End 在这段程序中,函数 A 嵌套了函数 B,函数 B 嵌套了函数 C。,2019年9月6日,第33页,2嵌套函数的调用 一个嵌套函数可以被下列函数调用: (1)该嵌套函数的上一层函数,如上面例 6-13 中函数 A 可以调用函数 B,函数 B 可以调用函数 C,但是函数 A 不能调用函数 C; (2)同一母函数下的同级嵌套函数,如上面例 6-12 中函数 B 可以调用函数 C; (3)被任一低级别的函数调用。,2019年9月6日,第34页,在
19、这段程序中,函数 A 包含了嵌套函数 B 和嵌套函数 D,函数 B 和函数 D 分别嵌套了函数 C 和函数 E。这段程序中函数间的调用关系为: (1)函数 A 为主函数,可以调用函数 B 和函数 D,但是不能调用函数 C 和函数 E; (2)函数 B 和函数 D 为一级嵌套函数,B 可以调用函数 D 和函数 C,但是不能调用函数 E;D 可以调用函数 B 和函数 E,但是不能调用 C; (3)函数 C 和函数 E 为分属两个函数的嵌套函数,可以调用函数 B 和函数 D,但是不能互相调用。,2019年9月6日,第35页,私有函数,私有函数是 MATLAB 中的另一类函数,这类函数位于名为“pri
20、vate”的子文件夹中,只能被上一级文件夹中的函数或者这些函数所调用的 M 文件调用。如,当前文件夹为 matlabmath,matlabmath 中包含子文件夹 private,则 private 中的函数只能被 matlabmath 根目录下的函数及这些函数调用的 M 文件调用。 私有函数只能被其父文件夹中的函数调用,因此,用户可以开发自己的函数库,函数的名称可以与系统标准 M 函数库名称相同,而不必担心在函数调用时发生冲突,因为 MATLAB 首先查找私有函数,再查找标准函数。,2019年9月6日,第36页,重载函数,函数重载为程序编写和用户调用都提供了很大的方便。函数重载允许多个函数使
21、用相同的函数名,不同的输入参数类型。在函数调用时,系统根据输入参数的情况自动选择相应的函数执行。,2019年9月6日,第37页,函数操作,函数句柄 利用函数句柄可以实现对函数的间接操作,可以通过将函数句柄传递给其他函数实现对函数的操作,也可以将函数句柄保存在变量中,留待以后调用操作。 函数句柄是通过 符号创建的,格式为: fhandle = functionname。,2019年9月6日,第38页,若要保存函数句柄,可以使用单元数组,如下: trigFun = sin, cos, tan; 通过函数句柄实现对函数的间接调用,其调用格式与直接调用函数的格式相同:fhandle(arg1, arg
22、2, ., argn),其中 fhandle 为函数句柄。,2019年9月6日,第39页,函数参数,当调用函数时,主调函数通过函数参数的形式向被调函数传递数据,被调函数通过函数返回值的形式向主调函数返回数据。本节介绍函数参数,内容包括:输入参数数目确定、输入可变数目的参数、向嵌套函数输入可选参数和修改参数值并返回。,2019年9月6日,第40页,1函数参数数目确定 函数 nargin 和函数 nargout 分别用于确定函数的输入输出参数个数。在函数体内部用 nargin(nargout)确定输入输出参数后可以用条件语句确定需要执行的操作。,2019年9月6日,第41页,函数 nargin 和
23、函数 nargout 允许函数接收或返回任意数目的参数。本节介绍参数数目可变的函数。 在 MATLAB 中,输入输出参数是以单元数组的形式进行传输的:输入参数以单元数组的形式传递给函数,单元数组的每个元素为相应的参数,同样,输出参数也是以单元数组的形式组织的。如此的参数组织形式便于函数接受任意数目的参数。见下面的例子。,2019年9月6日,第42页,在调用该函数时可以输入任意数目的参数,参数可以为二元数组或者表示线型的字符串,该函数将用指定的线型绘制输入数据的图像。指定线型的字符串可以在任意位置输入,并且可以输入多个,但是需要注意的是,只有最后一个字符串起作用。 在上面的程序中,将所有输入参数
24、作为一个单元数组,利用花括号和圆括号对数组元素进行访问,实现输入参数的调用。,2019年9月6日,第43页,在嵌套函数中也可以使用可变参数。但是需要注意的是,varargin、varargout、nargin 和 nargout 的意义可能有所不同。下面介绍这四个元素的应用规则。 varargin 和 varargout 这两个元素为变量,与 MATLAB 其他变量的作用范围相同。由于嵌套函数与主函数使用相同的工作区,因此 varargin 和 varargout 既可以表示嵌套函数的输入输出参数,也可以是主函数的输入输出函数,具体值取决于程序中的变量声明: 如果嵌套函数在函数声明中包含 va
25、rargin 或者 varargout,则在该函数内部调用这两个变量时,变量内容为该函数的输入输出参数; 如果嵌套函数声明中没有包含 varargin 或者 varargout,而在该函数的上层函数声明中包含 varargin 或者 varargout,则当在该嵌套函数内部调用这两个变量时,变量内容为上层函数的输入输出参数。,2019年9月6日,第44页,nargin 和 nargout nargin 和 nargout 是函数,当在函数中调用这两个函数时,其值为该函数的输入或输出参数,而不需要进行声明。如上面的例子中,在函数 A 中调用 nargin(B(nargin, y * rand(4
26、)) 表示函数 A 的输入参数个数,在函数 C 中调用 nargin 表示函数 C 的输入参数个数。,2019年9月6日,第45页,MATLAB 编程错误处理,通过 try-catch 语句检测错误 对错误进行处理并且从错误中恢复 消息标志符 警告处理,2019年9月6日,第46页,通过 try-catch 语句检测错误,无论程序的编写多么谨慎,在不同的环境下运行时都有可能产生意外的错误。因此,有必要在程序中添加错误检测语句,保证程序在所有的条件下都能够正常运行。 MATLAB 中的 try-catch 语句可用于错误检测。如果程序中的一些语句可能会产生非预计的结果,可以将这些语句放在 try
27、-catch 块中。try-catch 语句可以检测所有错误,并且分别进行处理。格式如下: try表达式1 catch表达式2 end 一个 try-catch 块分为两个部分。第一个部分以 try 开始,第二个部分以 catch 开始,整个块以 end 结束。程序首先正常执行第一部分,如果有错误发生,则停止执行该部分的其他语句,转而执行 catch 中的语句。catch 部分对错误进行处理,可以显示错误提示、执行默认语句等。,2019年9月6日,第47页,在 try-catch 语句中,可以嵌套其他的 try-catch 语句,其格式为: try表达式 1 % 执行表达式 1 catchtr
28、y表达式 2 % 尝试从错误中恢复catchdisp Operation failed % 处理错误end end,2019年9月6日,第48页,对错误进行处理并且从错误中恢复,1发出错误报告 MATALB 中 error 函数可以报告错误并且中断程序运行。用户可以通过指定 error 函数参数的方式指定将要发出的错误信息。,2019年9月6日,第49页,2识别错误发生的原因 当错误发生时,用户需要知道错误发生的位置及错误原因,以便能够正确处理错误。lasterror 函数可以返回最后发生的错误的相关信息,辅助用户识别错误。 lasterror 返回结果为一个结构体,该结构体包含三个域,分别为
29、 message、identifier、stack。message 为字符串,起内容为最近发生的错误的相关文本信息;identifier 也是一个字符串,内容为错误消息的类别标志;stack 为一结构体,其内容为该错误的堆栈中的相关信息。stack 包含三个域,为 file、name 和 line,分别为文件名、函数名和错误发生的行数。,2019年9月6日,第50页,3错误重现 在一些情况下,需要重现已经抛出过的错误,以便于对错误进行分析。MATLAB 中函数 rethrow 可以重新抛出指定的错误。该函数的格式为 rethrow(err),其中输入参数 err 用于指定需要重现的错误。该语句
30、执行后程序运行中断,将控制权转给键盘或 catch 语句的上一层模块。输入参数 err 需为 MATLAB 结构体,包含 message、identifier、stack 中至少一个域,这三个域的类型与 lasterror 返回结果相同。 rethrow 函数通常与 try-catch 语句一起使用。如: try表达式 1 catchdo_cleanuprethrow(lasterror) end,2019年9月6日,第51页,消息标志符,1消息标志符的格式 标志符为一个字符串,指定错误或警告消息的类别(component)及详细信息(mnemonic)。通常为“类别:详细信息”的格式。如:
31、MATLAB:divideByZero Simulink:actionNotTaken TechCorp:notFoundInPath 等。两个部分都需要满足如下的规则: (1)不能包含空格 (2)第一个字符必须为字母 (3)后面的字符可以为数字或下划线 类别部分指定错误或警告可能发生的大体位置,通常为某一产品的名字或者工具箱的名字,如 MATLAB 或者 Control。MATLAB 支持使用多层次的类别名称。 详细信息用于指定消息的具体内容,如除数为 0 等。 如下面的例子为一个完整的标志符: error(MATLAB:ambiguousSyntax, Syntax %s could be
32、 ambiguous.n, inputstr)。,2019年9月6日,第52页,2标志符的应用 消息标志符通常与 lasterror 函数一起应用,使得 lasterror 函数和 lasterr 函数能够识别错误的原因。lasterror 函数和 lasterr 函数返回消息标志符,用户可以通过其类别信息和详细信息分别获取错误的总体类别及具体信息。 使用消息标志符的第一步为确定目的信息并为其指定标志符。消息标志符通过 error 函数指定,格式为: error(msg_id, errormsg) error(msg_id, formatted_errormsg, arg1, arg2, .)
33、 其中的消息标志符可以省略。如果 lasterror 函数不使用该信息,上面的语句可以简写为: error(errormsg) 下面以两个实例说明消息标志符与 lasterror 的使用。,2019年9月6日,第53页,2019年9月6日,第54页,警告处理,警告用于提示用户在程序运行中出现异常情况。与错误不同的是,警告并不中断程序的运行,而是显示警告内容并继续执行。警告通过函数 warning 发出,格式与 error 函数相同,如: warning(Input must be a string) warning(formatted_warningmsg, arg1, arg2, .) wa
34、rning(Ambiguous parameter name, “%s“., param) 另外,与错误相同,警告也可以使用消息标志符,用以显示该警告信息的类别及具体信息。警告处理的方式与错误处理的方式类似这里不再赘述。,2019年9月6日,第55页,程序设计的辅助函数,表达式与函数的评估 计时器函数,2019年9月6日,第56页,2019年9月6日,第57页,计时器函数,2019年9月6日,第58页,调试程序,直接调试法 利用调试工具 采用命令行调试程序 采用调试界面调试程序,2019年9月6日,第59页,直接调试法,MATLAB 语言具有强大的运算能力,指令系统简单,因此程序通常非常简洁。
35、对于简单的程序可以采用直接调试的方法。 在程序调试时,程序运行中变量的值为一个重要的线索。因此,查看变量值为程序调试的重要线索,由于在函数调用时只返回最后的输出参数,而不返回中间变量,因此,可以选择下面的方法查看程序运行中的变量值。 (1)通过分析后,将可能出错的语句后面的分号(;)删除,将结果显示在命令窗口中,与预期值进行比较; (2)利用函数 disp 显示中间变量的值; (3)在程序中的适当位置添加 keyboard 指令。当 MATLAB 执行至此处时将暂停,等待用户反应。当程序运行至此时将暂停,在命令窗口中显示 k提示符,用户可以查看工作区中的变量,可以改变变量的值。输入 retur
36、n 指定返回程序,继续运行。 (4)在调试一个单独的函数时,可以将函数改写为脚本文件,此时可以直接对输入参数赋值,然后以脚本方式运行该 M 文件,这样可以保存中间变量,在运行完成后,可以查看中间变量的值,对结果进行分析,查找错误所在。,2019年9月6日,第60页,采用命令行调试程序,2019年9月6日,第61页,2019年9月6日,第62页,文本编辑器中的 Debug 菜单提供了全部的调试选项,另外,MATLAB 主窗口中的 Debug 菜单提供了一些调试命令,方便调试时在命令窗口中查看运行状态。调试选项及其功能如表所示。,2019年9月6日,第63页,Set/Clear Breakpoin
37、t,设置或清除断点。可以选择该选项对当前行进行操作,或者通过快捷键 F12,或者直接点击该行左侧的“-”,如图所示。设置断点时该处显示为红点。再次进行相同的操作则删除该断点。,2019年9月6日,第64页,Set/Modify Conditional Breakpoint,该选项用于设置或修改条件断点。条件断点为一种特殊的断点,当满足指定的条件时则程序执行至此时停止,条件不满足时则程序继续进行。其设置界面如图 6-6所示,在输入框中输入断点条件则将当前行设置为条件断点。,2019年9月6日,第65页,Enable/Disable Breakpoint,该选项用于开启或关闭当前行的断点,如果当前
38、行不存在断点,则设置当前行为断点;如果当前行是断点,则改变该断点的状态。在调试时,被关闭的断点将会被忽略。 在程序调试中,变量的值是查找错误的重要线索,在 MATLAB 中查看变量的值可以有三种方法: (1)在编辑器中将鼠标放置在待查看的变量处,停留,则在此处显示该变量的值; (2)在工作区浏览器中查看该变量的值; (3)在命令窗口中输入该变量的变量名,则显示该变量的值。 本节介绍了程序调试的函数和工具,在真正编写程序时,需要根据不同的情况灵活应用这些功能,达到最高的调试效率。,2019年9月6日,第66页,优化程序,通过 Profiler 进行程序运行分析 通过 tic、toc 函数进行程序
39、运行分析 程序优化的常用方法,2019年9月6日,第67页,通过 Profiler 进行程序运行分析,Profiler 工具为 MATLAB 中的图形用户接口,用于分析程序运行时各个部分所消耗的时间,辅助用户进行程序优化。通过 Profiler,用户可以: 避免由于疏忽造成的非必要操作 替换运算较慢的算法,选择快速算法 通过存储变量的方式避免重复计算 通过 Profiler 工具进行程序运行分析通常按照下面的步骤进行: (1)查看 Profiler 生成的总体报告,查找运行时间最多的函数或调用最频繁的函数。 (2)查看这些函数的详细报告,查找其中运行时间最多的语句或调用最频繁的语句。用户可以保
40、存第一次分析的结果,以便修改后再次分析时进行比较。 (3)确定在运行时间最多的函数或代码行是否存在改进的可能。 (4)点击界面链接,打开相应文件,进行修改。 (5)重复进行上述的分析、修改,直到得到满意结果。,2019年9月6日,第68页,1打开 Profiler MATLAB 中可以通过下列方式打开 Profiler: (1)点击 MATLAB 工具栏中的 Profiler 图标,激活 Profiler 工具; (2)选择 Desktop- Profiler; (3)对于已经在编辑器中打开的 M 文件,选择 Tools-Open Profiler; (4)选中命令历史窗口中的一个或多个命令,
41、点击右键,选择 Profile Code; (5)在命令窗口中输入:profile viewer。,2019年9月6日,第69页,2运行 Profiler Profiler 的界面如图所示。在 Run this code 中输入需要分析的命令或表达式,点击 Start Profiling,开始分析。需要注意的是,分析的表达式必须出于 MATLAB 的当前工作路径中,否则可能会得到错误的结果。,2019年9月6日,第70页,3查看分析结果 分析完成后,Profiler 会生成分析报告,包括总体报告和针对每个函数的详细报告。总体报告中包括函数名、被调用次数、总运行时间、函数单独运行时间(即不包括其
42、子函数的运行时间)及函数运行时间的图形显示,如图所示。用户可以点击每列的标题改变结果的排序方式,也可以点击函数标题查看该函数的详细报告。,2019年9月6日,第71页,函数详细报告中包括该函数中每行代码的被调用次数和运行时间,并且可以显示其中的子函数、函数列表等,如图所示。,2019年9月6日,第72页,4通过 profile 函数进行程序运行分析 Profiler 的运行主要是基于 profile 函数的运行结果。这里对 profile 函数的使用做简单的介绍。profile 函数的主要使用格式如表所示。,2019年9月6日,第73页,通过 tic、toc 函数进行程序运行分析,如果只需要了
43、解程序的运行时间,或者比较一段程序在不同应用条件下的运行速度,可以通过计时器来进行。计时器包含两个函数:tic 和 toc。tic 用于开始计时器,toc 用于关闭计时器,并计算程序运行的总时间。如 tic- 所需计时的程序代码 - toc 对于小程序,如果其运行时间非常短,可以通过将其多次运行,计算总体时间的方法进行,如: ticfor k = 1:100- 所需计时的程序代码 -end toc,2019年9月6日,第74页,程序优化的常用方法,使循环向量化 为数组预分配内存 以 MEX 文件的格式编写循环语句; 对向量赋值时尽量避免改变变量的类型或数组大小; 对实数进行操作,尽量避免复数的操作; 合理使用逻辑运算符; 避免重载 MATLAB 的内置函数和操作符; 通常情况下,函数的运行效率高于脚本文件; Load 和 Save 函数效率高于文件输入输出函数; 避免在运行 MATLAB 时运行其他大型后台程序。,