MATLAB 高级函数使用指南
1. 函数句柄的使用
1.1 匿名函数的保存与加载
在 MATLAB 中,调用函数时,即使不传递参数,也必须使用括号。匿名函数可以保存到 MAT - file 中,需要时再加载。以下是具体操作步骤:
1. 创建匿名函数:
cirarea = @ (radius) pi * radius .^2;
- 将匿名函数保存到 MAT - file:
save anonfns cirarea
- 清除当前工作区:
clear
- 加载保存的 MAT - file:
load anonfns
- 查看工作区变量:
who
输出结果会显示
cirarea
变量。还可以将其他匿名函数追加到这个 MAT - file 中,将相关的匿名函数组保存到 MAT - file 中通常很有用。
1.2 为其他函数创建句柄
函数句柄不仅可以为匿名函数创建,还可以为内置函数和用户定义的函数创建。例如,为内置的阶乘函数创建句柄:
facth = @factorial;
使用这个句柄调用函数:
facth(5)
输出结果为
120
。
1.3 函数函数
使用函数句柄的一个原因是能够将函数作为参数传递给其他函数,这些函数被称为函数函数。例如,有一个函数
fnfnexamp
用于绘制函数曲线:
function fnfnexamp(funh)
% Example of a function function. The handle of a function
% is passed and that function of x is plotted
x = 1:.25:6;
y = funh(x);
plot(x,y,'ko')
直接传递函数名会出错:
fnfnexamp(sin)
需要传递函数的句柄:
fnfnexamp(@sin)
也可以传递
@cos
等其他函数的句柄来绘制不同的曲线。
还可以使用
str2func
函数将字符串转换为函数句柄,使用
func2str
函数将函数句柄转换为字符串。例如:
function fnstrfn2(funstr)
% A function name is passed as an argument to this
% function; it converts this to a function handle and
% then plots the function of x
x = 1:.25:6;
funh = str2func(funstr);
y = funh(x);
plot(x,y,'bo')
调用方式为:
fnstrfn2('sin')
MATLAB 还有一些内置的函数函数,如
fplot
用于在指定范围内绘制函数曲线:
fplot(@sin, [-pi pi])
feval
函数用于计算函数句柄并执行指定参数的函数:
feval(@sin, 3.2)
1.4 练习 9.1
创建自己的匿名函数来计算圆、矩形和其他形状的面积,并将这些匿名函数存储在名为
myareas.mat
的文件中。
2. 可变数量的参数
2.1 可变数量的输入参数
在之前编写的函数中,输入和输出参数的数量通常是固定的,但也可以有可变数量的参数。可以使用内置的单元数组
varargin
来存储可变数量的输入参数,使用
nargin
函数返回传递给函数的输入参数数量。
例如,
areafori
函数可以接受 1 个或 2 个输入参数:
function area = areafori(varargin)
% Calculates and returns the area of a circle in feet
% The radius is passed, and potentially the unit of
% inches is also passed, in which case the result will be
% given in inches instead of feet
n = nargin; % number of input arguments
radius = varargin{1}; % Given in feet by default
if n == 2
unit = varargin{2};
% if inches is specified, convert the radius
if unit == 'i'
radius = radius * 12;
end
end
area = pi * radius ^ 2;
调用示例:
areafori(3)
areafori(1,'i')
也可以修改函数头,明确指定半径参数,再使用
varargin
处理剩余的可变参数:
function area = areafori2(radius, varargin)
% Calculates and returns the area of a circle in feet
% The radius is passed, and potentially the unit of
% inches is also passed, in which case the result will be
% given in inches instead of feet
n = nargin; % number of input arguments
if n == 2
unit = varargin{1};
% if inches is specified, convert the radius
if unit == 'i'
radius = radius * 12;
end
end
area = pi * radius ^ 2;
2.2 可变数量的输出参数
可以使用内置的单元数组
varargout
来存储可变数量的输出参数,使用
nargout
函数确定调用函数时期望返回的输出参数数量。
例如,
typesize
函数根据输入参数的类型返回不同数量的输出参数:
function [arrtype, varargout] = typesize(inputval)
% Demonstrates a variable number of output arguments
[r c ] = size(inputval);
if r==1 && c==1
arrtype = 's';
elseif r==1 || c==1
arrtype = 'v';
varargout{1} = length(inputval);
else
arrtype = 'm';
varargout{1} = r;
varargout{2} = c;
end
调用示例:
typesize(5)
[arrtype, len] = typesize(4:6)
[arrtype, r, c] = typesize([4:6;3:5])
mysize
函数根据
nargout
的值返回不同数量的输出参数:
function [row col varargout] = mysize(mat)
% Demonstrates the use of nargout
[row col] = size(mat);
if nargout == 3
varargout{1} = row*col;
end
调用示例:
[r c] = mysize(eye(3))
[r c elem] = mysize(eye(3))
2.3 练习 9.2
编写一个函数,接收一个
x
向量和一个函数句柄,创建一个
y
向量(该向量是
x
的函数),并绘制
x
和
y
向量的数据,同时在标题中显示函数名。
2.4 练习 9.3
编写一个名为
geomser
的函数,接收一个
r
值,计算并返回几何级数的和。如果传递第二个参数,则该参数为
n
的值;否则,函数为
n
生成一个 5 到 30 之间的随机整数。函数头如下:
function sgs = geomser(r, varargin)
3. 嵌套函数
3.1 嵌套函数的基本概念
函数可以像循环一样嵌套,外层函数可以包含内层函数。每个函数都必须有
end
语句。嵌套函数的一般格式如下:
outer function header
body of outer function
inner function header
body of inner function
end % inner function
more body of outer function
end % outer function
内层函数可以位于外层函数体的任何部分,外层函数体在内外层函数前后都可以有代码,也可以有多个内层函数。
3.2 变量的作用域
变量的作用域是定义和使用它的最外层函数的工作区。在外层函数中定义的变量可以在内层函数中使用,在内层函数中定义的变量如果在外层函数中未使用,则其作用域仅限于内层函数。
例如,
nestedvolume
函数计算立方体的体积,外层函数调用嵌套函数计算立方体底面的面积:
function outvol = nestedvolume(len, wid, ht)
% Demonstrates a nested function
outvol = base * ht;
function outbase = base
outbase = len * wid;
end % base function
end % nestedvolume function
调用示例:
v = nestedvolume(3,5,7)
输出结果为
105
。
输出参数与变量不同,输出参数的作用域仅限于嵌套函数,不能在外层函数中使用。例如,在
nestedvolume2
函数中,
outbase
只能在
base
函数中使用,
bvar
是
base
函数的局部变量,而
cvar
由于在外层函数中使用,其作用域为
nestedvolume2
函数的工作区。
function outvol = nestedvolume2(len, wid, ht)
% Demonstrates scope within a nested function
disp('This function calculates a volume')
% Call the base function, and calculate and
% print the volume
outvol = base * ht;
fprintf('outvol is %.1f\n', outvol)
fprintf('cvar is %.1f\n', cvar)
% Call the printstuff function
printstuff
% Not valid because it is an output argument:
% fprintf('outbase is %.1f\n', outbase)
function outbase = base
bvar = len * wid;
cvar = len * wid;
outbase = bvar;
end
function printstuff
fprintf('outvol is %.1f\n', outvol)
%Not valid because bvar is not used in nestedvolume2:
% fprintf('bvar is %.1f\n', bvar)
fprintf('cvar is %.1f\n', cvar)
end
end
4. 递归函数
4.1 递归的概念
递归是指事物用自身来定义。在编程中,递归函数是调用自身的函数。递归在编程中经常使用,但许多简单的例子(包括本节中的一些例子)实际上效率不高,可以用迭代方法(循环或 MATLAB 中的向量化代码)代替。
4.2 阶乘的递归定义
以阶乘为例,通常整数
n
的阶乘迭代定义为:
[n! = 1 \times 2 \times 3 \times \cdots \times n]
递归定义为:
[n! = n \times (n - 1)!](一般情况)
[1! = 1](基例)
递归定义包含一般情况和基例,基例用于终止递归。例如,计算
3!
的过程如下:
[3! = 3 \times 2!]
[2! = 2 \times 1!]
[1! = 1]
所以 (2! = 2),(3! = 6)。
4.3 递归函数的实现
编写递归函数
fact
来计算阶乘:
function facn = fact(n)
% This function recursively finds n!
if n == 1
facn = 1;
else
facn = n * fact(n−1);
end
调用示例:
fact(5)
输出结果与内置的
factorial
函数相同。
4.4 另一个递归函数示例
prtwords
函数用于将句子中的单词按逆序打印:
function prtwords(sent)
% This function recusively prints the words in a string
% in reverse order
[word, rest] = strtok(sent);
if ~isempty(rest)
prtwords(rest);
end
disp(word)
调用示例:
prtwords('what does this do')
输出结果为:
do
this
does
what
4.5 递归函数的执行流程
以下是
prtwords
函数的执行流程 mermaid 流程图:
graph TD;
A[接收句子] --> B[分割句子为单词和剩余部分];
B --> C{剩余部分是否为空};
C -- 否 --> D[递归调用 prtwords 处理剩余部分];
D --> E[打印当前单词];
C -- 是 --> E[打印当前单词];
4.6 总结
递归函数通过不断调用自身,利用基例终止递归,实现特定的功能。在使用递归函数时,要确保有基例且能在某个点达到基例,否则会导致无限递归。虽然递归在某些情况下很有用,但对于一些简单问题,迭代方法可能更高效。
表格总结
| 函数类型 | 特点 | 示例代码 |
|---|---|---|
| 函数句柄 | 可用于匿名函数、内置函数和用户定义函数,方便函数传递 |
facth = @factorial; facth(5)
|
| 可变参数函数 |
输入和输出参数数量可变,使用
varargin
和
varargout
|
function area = areafori(varargin)
|
| 嵌套函数 | 函数可以嵌套,变量作用域有特定规则 |
function outvol = nestedvolume(len, wid, ht)
|
| 递归函数 | 函数调用自身,包含基例和一般情况 |
function facn = fact(n)
|
5. 综合应用与实践
5.1 函数句柄与可变参数的结合应用
在实际应用中,函数句柄和可变参数可以结合使用,以实现更灵活的功能。例如,我们可以编写一个函数,它接受一个函数句柄和可变数量的输入参数,然后根据这些参数调用相应的函数。
function result = applyFunction(funh, varargin)
% 应用函数句柄到可变数量的输入参数
result = feval(funh, varargin{:});
end
调用示例:
% 调用 applyFunction 函数,传入 sin 函数句柄和参数 3.2
result = applyFunction(@sin, 3.2)
5.2 嵌套函数与递归函数的结合
嵌套函数和递归函数也可以结合使用,以实现复杂的功能。例如,我们可以编写一个嵌套的递归函数来计算斐波那契数列。
function fib = fibonacci(n)
% 计算斐波那契数列的第 n 项
fib = innerFib(n);
function f = innerFib(k)
% 内部递归函数
if k == 0 || k == 1
f = k;
else
f = innerFib(k - 1) + innerFib(k - 2);
end
end
end
调用示例:
% 计算斐波那契数列的第 6 项
fib = fibonacci(6)
5.3 实践项目:数据处理与可视化
我们可以结合上述知识,完成一个数据处理与可视化的实践项目。假设我们有一组数据,需要对其进行不同的处理,并将处理结果可视化。
% 生成示例数据
x = 1:0.1:10;
y = sin(x);
% 定义不同的处理函数
function1 = @(data) data.^2;
function2 = @(data) log(data);
% 定义一个函数来处理数据并绘制图形
function processAndPlot(data, funh, titleStr)
% 处理数据
processedData = feval(funh, data);
% 绘制图形
plot(x, processedData);
title(titleStr);
xlabel('x');
ylabel('y');
end
% 处理并绘制数据
processAndPlot(y, function1, 'Data Squared');
figure;
processAndPlot(y, function2, 'Log of Data');
5.4 实践项目流程 mermaid 流程图
graph TD;
A[生成示例数据] --> B[定义处理函数];
B --> C[定义处理并绘图函数];
C --> D[处理并绘制数据 1];
C --> E[处理并绘制数据 2];
6. 性能优化与注意事项
6.1 递归函数的性能问题
递归函数虽然简洁,但在处理大规模数据时可能会导致性能问题,因为递归调用会消耗大量的内存和时间。例如,在计算斐波那契数列时,递归方法会有大量的重复计算。可以使用迭代方法来优化性能。
function fib = fibonacciIterative(n)
% 迭代方法计算斐波那契数列
if n == 0 || n == 1
fib = n;
else
a = 0;
b = 1;
for i = 2:n
temp = a + b;
a = b;
b = temp;
end
fib = b;
end
end
6.2 可变参数函数的使用注意事项
在使用可变参数函数时,要注意参数的类型和数量。特别是在处理
varargin
和
varargout
时,要确保对不同类型的参数进行正确的处理。例如,在
areafori
函数中,要确保第二个参数是正确的单位标识。
6.3 函数句柄的内存管理
函数句柄本身占用的内存较小,但在使用大量函数句柄时,也要注意内存管理。避免不必要的函数句柄创建和存储。
7. 总结与展望
7.1 知识总结
通过本文的学习,我们了解了 MATLAB 中函数句柄、可变数量的参数、嵌套函数和递归函数的使用方法。以下是对这些知识的总结表格:
| 知识类型 | 关键要点 |
|---|---|
| 函数句柄 |
可用于匿名函数、内置函数和用户定义函数,方便函数传递和调用,使用
@
运算符获取函数句柄
|
| 可变数量的参数 |
输入参数使用
varargin
存储,输出参数使用
varargout
存储,
nargin
和
nargout
用于获取参数数量
|
| 嵌套函数 | 函数可以嵌套,变量作用域与函数嵌套层次有关,输出参数作用域仅限于嵌套函数 |
| 递归函数 | 函数调用自身,包含基例和一般情况,基例用于终止递归,使用时要注意性能问题 |
7.2 未来展望
这些高级函数的使用可以帮助我们编写更灵活、更高效的 MATLAB 代码。在未来的应用中,我们可以将这些知识应用到更复杂的领域,如机器学习、数据分析等。同时,不断探索和优化这些函数的使用方法,以提高代码的性能和可读性。
7.3 学习建议
为了更好地掌握这些知识,建议多进行实践,编写不同类型的函数,并尝试将它们组合使用。同时,阅读优秀的 MATLAB 代码,学习他人的编程思路和技巧。
参考代码列表
- 函数句柄相关代码:
facth = @factorial;
facth(5)
- 可变参数函数相关代码:
function area = areafori(varargin)
n = nargin;
radius = varargin{1};
if n == 2
unit = varargin{2};
if unit == 'i'
radius = radius * 12;
end
end
area = pi * radius ^ 2;
end
- 嵌套函数相关代码:
function outvol = nestedvolume(len, wid, ht)
outvol = base * ht;
function outbase = base
outbase = len * wid;
end
end
- 递归函数相关代码:
function facn = fact(n)
if n == 1
facn = 1;
else
facn = n * fact(n - 1);
end
end
超级会员免费看
461

被折叠的 条评论
为什么被折叠?



