一.简介

本篇参考官方入门文档编写

前提准备:

  1. MATLAB

二. 快速入门(七)

1. 创建网格图和曲面图

关于网格图和曲面图

MATLAB® 在 x-y 平面中的网格上方使用点的 z 坐标来定义曲面图,并使用直线连接相邻的点。meshsurf 函数以三维形式显示曲面图。

  • mesh 生成仅使用颜色来标记连接定义点的线条的线框曲面图。
  • surf 使用颜色显示曲面图的连接线和面。

MATLAB 通过将索引的 z 数据值映射到图窗颜色图来标记曲面图颜色。

可视化包含两个变量的函数

要显示包含两个变量的函数 z = f (x,y),

  1. 在此函数的域中,生成分别由重复行和重复列组成的 XY 矩阵。
  2. 使用 XY 计算此函数并绘制其图形。

meshgrid 函数将一个向量或两个向量(即 xy)指定的域转换为矩阵 XY,以便用于计算包含两个变量的函数。X 的行是向量 x 的副本,Y 的列是向量 y 的副本。

绘制正弦函数

尝试此示例Copy Command Copy Code

此示例说明如何计算和绘制 xy 方向之间的二维 sinc 函数 sin(R)/RR 是距原点的距离,原点在矩阵的中心。添加 eps(非常小的值)可防止网格图在 R = 0 处的点出现孔洞。

1
2
3
4
[X,Y] = meshgrid(-8:.5:8); 
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
mesh(X,Y,Z)

Figure contains an axes object. The axes object contains an object of type surface.

image-20220724090404773

默认情况下,MATLAB 使用当前颜色图来标记网格图颜色。

彩色曲面图

尝试此示例Copy Command Copy Code

此示例说明如何将 sinc 函数绘制为曲面图,指定颜色图并添加颜色栏以便显示数据与颜色的映射。

曲面图与网格图相似,但曲面图的矩形面是彩色的。各个面的颜色由 Z 的值及颜色图(即颜色的有序列表)决定。

1
2
3
4
5
6
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
surf(X,Y,Z)
colormap hsv
colorbar

Figure contains an axes object. The axes object contains an object of type surface.

image-20220724090443552

将曲面图设置为透明

尝试此示例Copy Command Copy Code

此示例展示如何将曲面图的面设置为不同透明度。透明度(称为 alpha 值)可以针对整个对象进行指定,也可以基于 alphamap(其作用方式与颜色图类似)进行指定。

1
2
3
4
5
6
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
surf(X,Y,Z)
colormap hsv
alpha(.4)

Figure contains an axes object. The axes object contains an object of type surface.

image-20220724090507206

MATLAB 显示一个面 alpha 值为 0.4 的曲面。Alpha 值的范围介于 0(完全透明)和 1(不透明)之间。

使用灯光照亮曲面图

尝试此示例Copy Command Copy Code

本示例展示的曲面图与前面示例所用的曲面图相同,但将其设置为红色,并删除了网格线。然后会在“相机”(相机即为您观察曲面图所处的空间位置)左侧添加一个灯光对象:

1
2
3
4
5
6
[X,Y] = meshgrid(-8:.5:8);
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
surf(X,Y,Z,'FaceColor','red','EdgeColor','none')
camlight left;
lighting phong

Figure contains an axes object. The axes object contains an object of type surface.

image-20220724090536466

光照是使用定向光源照亮对象的技术。在特定情况下,此技术能够更清楚地显示曲面图形状的细微差异。光照还可用于增添三维图形的真实感。

操作曲面图

图窗工具栏和相机工具栏提供了以交互方式浏览三维图形的方法。通过从图窗视图菜单中选择相机工具栏可以显示相机工具栏。

下图显示选择了三维旋转工具的两个工具栏。

img

这些工具使您能围绕曲面图对象移动相机、缩放、添加光照并执行其他查看操作,而不需执行其他命令。

2. 显示图像

图像数据

您可以将二维数值数组显示为图像。在图像中,数组元素决定了图像的亮度或颜色。例如,加载一个图像数组及其颜色图:

1
2
3
4
5
6
7
load durer
whos
Name Size Bytes Class

X 648x509 2638656 double array
caption 2x28 112 char array
map 128x3 3072 double array

加载文件 durer.mat,向工作区添加三个变量。数组 X 是一个 648×509 矩阵,map 是作为此图像的颜色图的 128×3 数组。

MAT 文件(例如 durer.mat)是用于提供保存 MATLAB® 变量的方法的二进制文件。

X 的元素是介于 1 和 128 之间的整数,用作颜色图 map 的索引。要显示图像,请使用 imshow 函数:

1
imshow(X,map)

重新生成阿尔布雷特•丢勒的蚀刻板画。

img

image-20220724091402197

读取和写入图像

使用 imread 函数可以读取标准图像文件(TIFF、JPEG、PNG 等)。imread 返回的数据类型取决于读取的图像类型。

使用 imwrite 函数可以将 MATLAB 数据写入到各种标准图像格式。

3. 打印图形

打印概述

可以在与计算机连接的打印机上直接打印 MATLAB® 图窗,也可以将图窗导出到 MATLAB 支持的某种标准图形文件格式。打印和导出图窗有两种方法:

  • 使用文件菜单下的打印打印预览导出设置 GUI 选项。
  • 使用 print 命令即可通过命令行来打印或导出图窗。

使用 print 命令可以更好地控制驱动程序和文件格式。使用“打印预览”对话框可以更好地控制图窗大小、比例、位置和页面标题。

从“文件”菜单打印

文件菜单下包含两个与打印相关的菜单选项:

  • 打印预览选项可显示一个对话框,用于在预览输出页面时设置要打印的图窗的布局和图窗样式,您可以从此对话框打印图窗。此对话框包含以前包含在“页面设置”对话框中的选项。
  • 打印选项可显示一个对话框,用于选择打印机、选择标准打印选项和打印图窗。

使用打印预览可以确定打印输出是否符合您的要求。点击“打印预览”对话框上的帮助按钮将显示如何设置页面的信息。

将图窗导出到图形文件

文件菜单中的导出设置选项可打开一个 GUI,用于设置要保存为图形文件的图窗的文本大小、字体和样式等图形特征。“导出设置”对话框用于定义和应用模板以便自定义和标准化输出。设置之后,您可以将图窗导出为多种标准图形文件格式,例如 EPS、PNG 和 TIFF。

使用 Print 命令

print 命令为发送给打印机的输出类型提供了更大灵活性,并且允许您通过函数和脚本文件来控制打印。结果可以直接发送到默认打印机,也可以存储在特定的输出文件中。可以使用多种输出格式,包括 TIFF、JPEG 和 PNG。

例如,此语句将当前图窗窗口的内容作为 PNG 图形存储在名为 magicsquare.png 的文件中。

1
print -dpng magicsquare.png

要以屏幕上的图窗的同等大小保存图窗,请使用下列语句:

1
2
set(gcf,'PaperPositionMode','auto')
print -dpng -r0 magicsquare.png

要将同一图窗存储为 TIFF 文件(分辨率为 200 dpi),请使用以下命令:

1
print -dtiff -r200 magicsquare.tiff

如果在命令行中键入 print

1
print

将在默认打印机上打印当前图窗。

4. 处理图形对象

图形对象

图形对象是用于显示图形的基本元素。这些对象按层次结构组织,如下图所示。

img

当调用绘图函数时,MATLAB® 使用各种图形对象(例如,图窗窗口、轴、线条、文本等)创建图形。每个对象都具有一组固定的属性,您可以使用这些属性控制图形的行为和外观。

例如,以下语句使用变量 y 中的数据创建条形图,并设置关于条形显示方式的属性:

1
2
y = [75 91 105 123.5 131 150 179 203 226 249 281.5];
bar(y,'FaceColor','green','EdgeColor','black','LineWidth',1.5)

常见图形对象

当调用函数以便创建图形时,MATLAB 会创建图形对象的层次结构。例如,调用 plot 函数会创建下列图形对象:

  • 图窗 - 包含轴、工具栏、菜单等的窗口。
  • 轴 - 包含表示数据的对象的坐标系
  • 线条 - 代表传递至 plot 函数的数据值的线条。
  • 文本 - 用于轴刻度线和可选标题及注释的标签。

不同类型的图形使用不同对象来表示数据。由于存在许多种图形,因此也存在许多数据对象类型。其中一些用于一般用途,例如线条和矩形,还有一些是用于高度专业的用途,例如误差条、颜色栏和图例。

访问对象属性

绘图函数可返回用于创建图形的对象。例如,以下语句将创建一个图形并返回由 plot 函数创建的线条对象:

1
2
3
x = 1:10;
y = x.^3;
h = plot(x,y);

使用 h 来设置线条对象的属性。例如,设置它的 Color 属性。

1
h.Color = 'red';

此外,也可以在调用绘图函数时指定线条属性。

1
h = plot(x,y,'Color','red');

可以查询线条属性以便查看当前值:

1
2
3
h.LineWidth
ans =
0.5000

查找对象的属性

要查看对象的属性,请输入:

1
get(h)

MATLAB 将返回包含对象属性及当前值的列表。

要查看对象属性及可能的值信息,请输入:

1
set(h)

设置对象属性

可使用 set 函数一次设置多个属性。

设置现有对象的属性

要对多个对象的同一属性设置相同值,请使用 set 函数。

例如,下面的语句绘制一个 5×5 矩阵(创建五个线条对象,每列各一个),然后将 Marker 属性设置为正方形,并将 MarkerFaceColor 属性设置为绿色。

1
2
3
y = magic(5);
h = plot(y);
set(h,'Marker','s','MarkerFaceColor','g')

在本示例中,h 是一个包含五个句柄的向量,图形中的每个线条(共五个)各一个句柄。set 语句将所有线条的 MarkerMarkerFaceColor 属性设置为相同值。

要对一个对象设置属性值,请对句柄数组建立索引:

1
h(1).LineWidth = 2;

设置多个属性值

如果要将每个线条的属性设置为不同值,您可以使用元胞数组存储所有数据,并将其传递给 set 命令。例如,创建绘图并保存线条句柄:

1
2
3
figure
y = magic(5);
h = plot(y);

假定您要为每个线条添加不同标记,并使标记的面颜色与线条的颜色相同。您需要定义两个元胞数组,一个包含属性名,另一个包含属性所需的值。

prop_name 元胞数组包含两个元素:

1
2
prop_name(1) = {'Marker'};
prop_name(2) = {'MarkerFaceColor'};

prop_values 元胞数组包含 10 个值:Marker 属性有 5 个值,MarkerFaceColor 属性有 5 个值。请注意,prop_values 是一个二维元胞数组。第一个维表示值应用于 h 中的哪个句柄,第二个维表示值分配给哪个属性:

1
2
3
4
5
6
7
8
9
10
prop_values(1,1) = {'s'};
prop_values(1,2) = {h(1).Color};
prop_values(2,1) = {'d'};
prop_values(2,2) = {h(2).Color};
prop_values(3,1) = {'o'};
prop_values(3,2) = {h(3).Color};
prop_values(4,1) = {'p'};
prop_values(4,2) = {h(4).Color};
prop_values(5,1) = {'h'};
prop_values(5,2) = {h(5).Color};

MarkerFaceColor 始终分配到相应线条的颜色的值(通过获取线条 Color 属性获得)。

定义元胞数组之后,调用 set 以便指定新属性值:

1
set(h,prop_name,prop_values)

img

用于处理对象的函数

此表列出了处理对象时常用的函数。

函数 用途
allchild 查找指定对象的所有子级。
ancestor 查找图形对象的前代。
copyobj 复制图形对象。
delete 删除对象。
findall 查找所有图形对象(包括隐藏句柄)。
findobj 查找具有指定属性值的对象的句柄。
gca 返回当前轴的句柄。
gcf 返回当前图窗的句柄。
gco 返回当前对象的句柄。
get 查询对象的属性的值。
ishandle 如果值是有效对象句柄,则为 True。
set 设置对象的属性的值。

传递参数

可定义专用绘图函数以简化自定义图形的创建过程。通过定义函数,可以像 MATLAB 绘图函数一样传递参数。

下面的示例显示了一个 MATLAB 函数,该函数在输入参数 x 指定的范围中计算数学表达式,然后绘制结果。第二次调用 plot 函数会将结果的 mean 值绘制为红线。

该函数基于计算值修改 y 轴刻度。加入轴标签和标题后,即完成了图形自定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function plotFunc(x)
y = 1.5*cos(x) + 6*exp(-.1*x) + exp(.07*x).*sin(3*x);
ym = mean(y);
hfig = figure('Name','Function and Mean');
hax = axes('Parent',hfig);
plot(hax,x,y)
hold on
plot(hax,[min(x) max(x)],[ym ym],'Color','red')
hold off
ylab = hax.YTick;
new_ylab = sort([ylab, ym]);
hax.YTick = new_ylab;
title ('y = 1.5cos(x) + 6e^{-0.1x} + e^{0.07x}sin(3x)')
xlabel('X Axis')
ylabel('Y Axis')
end

定义输入参数的值,并调用此函数。

1
2
x = -10:.005:40;
plotFunc(x)

img

查找现有对象的句柄

findobj 函数可用于通过搜索具有特定属性值的对象来获取图形对象的句柄。使用 findobj,您可以指定任何属性组合的值,这样可以方便地从多个对象中选取一个对象。此外,findobj 还可识别正则表达式。

查找特定类型的所有对象

由于所有对象都具有标识对象类型的 Type 属性,因此可以查找特定对象类型的所有匹配项的句柄。例如,

1
h = findobj('Type','patch');

查找所有补片对象的句柄。

查找具有特定属性的对象

您可以指定多个属性以便缩小搜索范围。例如,

1
2
plot(rand(5),'r:')
h = findobj('Type','line','Color','r','LineStyle',':');

查找所有红色点线的句柄。

1
2
3
4
5
6
7
8
9
h = 

5x1 Line array:

Line
Line
Line
Line
Line

限制搜索范围

通过将起始图窗或轴的句柄作为传递的第一个参数,您可以在对象层次结构中指定起点。例如,

1
h = findobj(gca,'Type','text','String','\pi/2');

仅在当前坐标区中查找 π/2。

5. 控制流

条件控制 - if、else、switch

条件语句可用于在运行时选择要执行的代码块。最简单的条件语句为 if 语句。例如:

1
2
3
4
5
6
7
8
% Generate a random number
a = randi(100, 1);

% If it is even, divide by 2
if rem(a, 2) == 0
disp('a is even')
b = a/2;
end

通过使用可选关键字 elseifelseif 语句可以包含备用选项。例如:

1
2
3
4
5
6
7
8
9
a = randi(100, 1);

if a < 30
disp('small')
elseif a < 80
disp('medium')
else
disp('large')
end

再者,当您希望针对一组已知值测试相等性时,请使用 switch 语句。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[dayNum, dayString] = weekday(date, 'long', 'en_US');

switch dayString
case 'Monday'
disp('Start of the work week')
case 'Tuesday'
disp('Day 2')
case 'Wednesday'
disp('Day 3')
case 'Thursday'
disp('Day 4')
case 'Friday'
disp('Last day of the work week')
otherwise
disp('Weekend!')
end

对于 ifswitch,MATLAB® 执行与第一个 true 条件相对应的代码,然后退出该代码块。每个条件语句都需要 end 关键字。

一般而言,如果您具有多个可能的离散已知值,读取 switch 语句比读取 if 语句更容易。但是,无法测试 switchcase 值之间的不相等性。例如,无法使用 switch 实现以下类型的条件:

1
2
3
4
5
6
7
8
9
yourNumber = input('Enter a number: ');

if yourNumber < 0
disp('Negative')
elseif yourNumber > 0
disp('Positive')
else
disp('Zero')
end

条件语句中的数组比较

了解如何将关系运算符和 if 语句用于矩阵非常重要。如果您希望检查两个变量之间的相等性,您可以使用

1
if A == B, ...

这是有效的 MATLAB 代码,并且当 AB 为标量时,此代码会如期运行。但是,当 AB 为矩阵时,用 A == B 不会测试二者是否相等,而会测试二者相等的位置;结果会生成另一个由 0 和 1 构成的矩阵,并显示元素与元素的相等性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
A = magic(4);
B = A;
B(1,1) = 0;

A == B

ans =

4×4 logical array

0 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

检查两个变量之间的相等性的正确方法是使用 isequal 函数:

1
if isequal(A, B), ...

isequal 返回 1(表示 true)或 0(表示 false)的标量逻辑值,而不会返回矩阵,因此能被用于 if 函数计算表达式。通过使用上面的 AB 矩阵,您可以获得

1
2
3
4
5
6
7
isequal(A,B)

ans =

logical

0

下面给出另一示例来重点介绍这一点。如果 AB 为标量,下面的程序永远不会出现“意外状态”。但是对于大多数矩阵对(包括交换列的幻方矩阵),所有元素均不满足任何矩阵条件 A > BA < BA == B,因此将执行 else 子句:

1
2
3
4
5
6
7
8
9
if A > B
'greater'
elseif A < B
'less'
elseif A == B
'equal'
else
error('Unexpected situation')
end

有几个函数对减少标量条件的矩阵比较结果以便用于 if 非常有用,这些函数包括

1
2
3
4
isequal
isempty
all
any

循环控制 - for、while、continue、break

此部分涵盖为程序循环提供控制的 MATLAB 函数。

for

for 循环按预先确定的固定次数重复一组语句。匹配的 end 用于界定语句结尾:

1
2
3
4
for n = 3:32
r(n) = rank(magic(n));
end
r

内部语句的终止分号禁止了循环中的重复输出,循环后的 r 显示最终结果。

最好对循环进行缩进处理以便于阅读,特别是使用嵌套循环时:

1
2
3
4
5
for i = 1:m
for j = 1:n
H(i,j) = 1/(i+j);
end
end

while

while 在逻辑条件的控制下将一组语句重复无限次。匹配的 end 用于界定语句结尾。

下面是一个完整的程序,用于演示如何使用 whileifelseend 来寻找区间对分法求多项式的零。

1
2
3
4
5
6
7
8
9
10
11
12
a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
x = (a+b)/2;
fx = x^3-2*x-5;
if sign(fx) == sign(fa)
a = x; fa = fx;
else
b = x; fb = fx;
end
end
x

结果生成多项式 x3 - 2x - 5 的根,即

1
2
x =
2.09455148154233

if 语句部分中讨论的与矩阵比较相关的注意事项同样适用于 while 语句。

continue

continue 语句将控制传递给它所在的 for 循环或 while 循环的下一迭代,并跳过循环体中的任何其余语句。此道理同样适用于嵌套循环中的 continue 语句。也就是说,执行会从遇到 continue 语句的循环开头继续。

下面的示例演示的 magic.m 循环计算文件中的代码行数目的 continue 循环,并跳过所有空行和注释。continue 语句用于前进到 magic.m 中的下一行,而不会在遇到空行或注释行时增加行计数:

1
2
3
4
5
6
7
8
9
10
11
fid = fopen('magic.m','r');
count = 0;
while ~feof(fid)
line = fgetl(fid);
if isempty(line) || strncmp(line,'%',1) || ~ischar(line)
continue
end
count = count + 1;
end
fprintf('%d lines\n',count);
fclose(fid);

break

break 语句用于提前从 for 循环或 while 循环中退出。在嵌套循环中,break 仅从最里面的循环退出。

下面对前述部分中的示例进行了改进。使用此 break 的优点是什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
a = 0; fa = -Inf;
b = 3; fb = Inf;
while b-a > eps*b
x = (a+b)/2;
fx = x^3-2*x-5;
if fx == 0
break
elseif sign(fx) == sign(fa)
a = x; fa = fx;
else
b = x; fb = fx;
end
end
x

程序终止 - return

此部分包含用于在程序运行完成之前终止程序的 MATLAB return 函数。

return

return 终止当前命令序列,并将控制权返回给调用函数或键盘。此外,return 还用于终止 keyboard 模式。被调用的函数通常在到达函数末尾时将控制权转交给调用它的函数。您可以在被调用的函数中插入一个 return 语句,以便强制提前终止并将控制权转交给调用函数。

向量化

提高 MATLAB 程序的运行速度的一种方法是向量化构造程序时所使用的算法。其他编程语言可使用 for 循环或 DO 循环,而 MATLAB 可使用向量或矩阵运算。下面提供了一个与创建算法表相关的简单示例:

1
2
3
4
5
6
x = 0.01;
y = log10(x);
for k = 1:999
x(k+1) = x(k) + 0.01;
y(k+1) = log10(x(k+1));
end

相同代码段的向量化版本为

1
2
x = .01:.01:10;
y = log10(x);

对于更复杂的代码,向量化选项并不总是这么明显。

预分配

如果无法向量化某段代码,可以通过预分配存储输出结果的任何向量或数组来提高 for 循环的运行速度。例如,此代码使用函数 zeros 来预分配在 for 循环中创建的向量。这显著提高了 for 循环的执行速度:

1
2
3
4
r = zeros(32,1);
for n = 1:32
r(n) = rank(magic(n));
end

如果未经过上述示例中的预分配,MATLAB 解释器会在每次遍历循环时将 r 向量增大一个元素。向量预分配避免了此步骤,并提高了执行速度。

6. 脚本和函数

概述

MATLAB® 提供了一个强大的编程语言和交互式计算环境。您可以使用此语言在 MATLAB 命令行中一次输入一个命令,也可以向某个文件写入一系列命令,按照执行任何 MATLAB 函数的相同方式来执行这些命令。使用 MATLAB 编辑器或任何其他文件编辑器可以创建您自己的函数文件。按照调用任何其他 MATLAB 函数或命令的相同方式来调用这些函数。

两种程序文件:

  • 脚本,不接受输入参数或返回输出参数。它们处理工作区中的数据。
  • 函数,可接受输入参数,并返回输出参数。内部变量是函数的局部变量。

如果您是新 MATLAB 程序员,您只需在当前文件夹中创建您希望尝试的程序文件。当您创建的文件越来越多时,您可能希望将这些文件组织到其他文件夹和个人工具箱,以便将其添加到您的 MATLAB 搜索路径中。

如果您复制多个函数名称,MATLAB 会执行在搜索路径中显示的第一个函数。

要查看程序文件(例如,myfunction.m)的内容,请使用

1
type myfunction

脚本

当调用脚本时,MATLAB 仅执行在文件中找到的命令。脚本可以处理工作区中的现有数据,也可以创建要在其中运行脚本的新数据。尽管脚本不会返回输出参数,其创建的任何变量都会保留在工作区中,以便在后续计算中使用。此外,脚本可以使用 plot 等函数生成图形输出。

例如,创建一个名为 magicrank.m 的文件,该文件包含下列 MATLAB 命令:

1
2
3
4
5
6
% Investigate the rank of magic squares
r = zeros(1,32);
for n = 3:32
r(n) = rank(magic(n));
end
bar(r)

键入语句

1
magicrank

使 MATLAB 执行命令、计算前 30 个幻方矩阵的秩,并绘制结果的条形图。执行完文件之后,变量 nr 将保留在工作区中。

img

函数

函数是可接受输入参数并返回输出参数的文件。文件名和函数名称应当相同。函数处理其自己的工作区中的变量,此工作区不同于您在 MATLAB 命令提示符下访问的工作区。

rank 提供了一个很好的示例。文件 rank.m 位于文件夹

1
toolbox/matlab/matfun

您可以使用以下命令查看文件

1
type rank

下面列出了此文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
function r = rank(A,tol)
% RANK Matrix rank.
% RANK(A) provides an estimate of the number of linearly
% independent rows or columns of a matrix A.
% RANK(A,tol) is the number of singular values of A
% that are larger than tol.
% RANK(A) uses the default tol = max(size(A)) * norm(A) * eps.

s = svd(A);
if nargin==1
tol = max(size(A)') * max(s) * eps;
end
r = sum(s > tol);

函数的第一行以关键字 function 开头。它提供函数名称和参数顺序。本示例中具有两个输入参数和一个输出参数。

第一个空行或可执行代码行前面的后续几个行是提供帮助文本的注释行。当键入以下命令时,会输出这些行

1
help rank

帮助文本的第一行是 H1 行,当对文件夹使用 lookfor 命令或请求 help 时,MATLAB 会显示此行。

文件的其余部分是用于定义函数的可执行 MATLAB 代码。函数体中引入的变量 s 以及第一行中的变量(即 rAtol)均为函数的局部变量;他们不同于 MATLAB 工作区中的任何变量。

本示例演示了 MATLAB 函数不同于其他编程语言函数的一个方面,即可变数目的参数。可以采用多种不同方法使用 rank 函数:

1
2
3
rank(A)
r = rank(A)
r = rank(A,1.e-6)

许多函数都按此方式运行。如果未提供输出参数,结果会存储在 ans 中。如果未提供第二个输入参数,此函数会运用默认值进行计算。函数体中提供了两个名为 narginnargout 的数量,用于告知与函数的每次特定使用相关的输入和输出参数的数目。rank 函数使用 nargin,而不需要使用 nargout

函数类型

MATLAB 提供了多种不同函数用于编程。

匿名函数

匿名函数是一种简单形式的 MATLAB 函数,该函数在一个 MATLAB 语句中定义。它包含一个 MATLAB 表达式和任意数目的输入和输出参数。您可以直接在 MATLAB 命令行中定义匿名函数,也可以在函数或脚本中定义匿名函数。这样,您可以快速创建简单函数,而不必每次为函数创建文件。

根据表达式创建匿名函数的语法为

1
f = @(arglist)expression

下面的语句创建一个求某个数字的平方的匿名函数。当调用此函数时,MATLAB 会将您传入的值赋值给变量 x,然后在方程 x.^2 中使用 x

1
sqr = @(x) x.^2;

要执行 sqr 函数,请键入

1
2
3
a = sqr(5)
a =
25

主函数和局部函数

任何非匿名函数必须在文件中定义。每个此类函数文件都包含一个必需的主函数(最先显示)和任意数目的局部函数(位于主函数后面)。主函数的作用域比局部函数更广。因此,主函数可以从定义这些函数的文件外(例如,从 MATLAB 命令行或从其他文件的函数中)调用,而局部函数则没有此功能。局部函数仅对其自己的文件中的主函数和其他局部函数可见。

函数部分中显示的 rank 函数就是一个主函数的示例。

私有函数

私有函数是一种主函数。其特有的特征是:仅对一组有限的其他函数可见。如果您希望限制对某个函数的访问,或者当您选择不公开某个函数的实现时,此种函数非常有用。

私有函数位于带专有名称 private 的子文件夹中。它们是仅可在母文件夹中可见的函数。例如,假定文件夹 newmath 位于 MATLAB 搜索路径中。newmath 的名为 private 子文件夹可包含只能供 newmath 中的函数调用的特定函数。

由于私有函数在父文件夹外部不可见,因此可以使用与其他文件夹中的函数相同的名称。如果您希望创建您自己的特定函数的版本,并在其他文件夹中保留原始函数,此功能非常有用。由于 MATLAB 在标准函数之前搜索私有函数,因此在查找名为 test.m 的非私有文件之前,它将查找名为 test.m 的私有函数。

嵌套函数

您可以在函数体中定义其他函数。这些函数称为外部函数中的嵌套函数。嵌套函数包含任何其他函数的任何或所有组成部分。在本示例中,函数 B 嵌套在函数 A 中:

1
2
3
4
5
6
7
8
function x = A(p1, p2)
...
B(p2)
function y = B(p3)
...
end
...
end

与其他函数一样,嵌套函数具有其自己的工作区,可用于存储函数所使用的变量。但是,它还可以访问其嵌套在的所有函数的工作区。因此,举例来说,主函数赋值的变量可以由嵌套在主函数中的任意级别的函数读取或覆盖。类似地,嵌套函数中赋值的变量可以由包含该函数的任何函数读取或被覆盖。

全局变量

如果您想要多个函数共享一个变量副本,只需在所有函数中将此变量声明为 global。如果您想要基础工作区访问此变量,请在命令行中执行相同操作。全局声明必须在函数中实际使用变量之前进行。全局变量名称使用大写字母有助于将其与其他变量区分开来,但这不是必需的。例如,在名为 falling.m 的文件创建一个新函数:

1
2
3
function h = falling(t)
global GRAVITY
h = 1/2*GRAVITY*t.^2;

然后,以交互方式输入语句

1
2
3
global GRAVITY
GRAVITY = 32;
y = falling((0:.1:5)');

通过上述两条全局语句,可以在函数内使用在命令提示符下赋值给 GRAVITY 的值。然后,您可以按交互方式修改 GRAVITY 并获取新解,而不必编辑任何文件。

命令与函数语法

您可以编写接受字符参数的 MATLAB 函数,而不必使用括号和引号。也就是说,MATLAB 将

1
foo a b c

解释为

1
foo('a','b','c')

但是,当使用不带引号的命令格式时,MATLAB 无法返回输出参数。例如,

1
legend apples oranges

使用 applesoranges 作为标签在绘图上创建图例。如果您想要 legend 命令返回其输出参数,必须使用带引号的格式:

1
[legh,objh] = legend('apples','oranges');

此外,如果其中任一参数不是字符向量,必须使用带引号的格式。

小心

虽然不带引号的命令语法非常方便,但在某些情况下可能会出现使用不当的情形,而 MATLAB 并不会产生错误信息。

在代码中构造字符参数

带引号的函数格式可用于在代码中构造字符参数。下面的示例处理多个数据文件,即 August1.datAugust2.dat 等。它使用函数 int2str,该函数将整数转换为字符以便生成文件名:

1
2
3
4
5
for d = 1:31
s = ['August' int2str(d) '.dat'];
load(s)
% Code to process the contents of the d-th file
end