我试图理解MATLAB脚本的以下命令:
global operatorObj
calcEVR_handles = operatorObj.calcEVR_handles;
m = operatorObj.nInputs
E = zeros(m,1);
V = zeros(m,1);
R = zeros(m,m);
for i=1:m
[E(i), V(i), R(i,i)] = calcEVR_handles{i}(t,x);
end
Run Code Online (Sandbox Code Playgroud)
可能calcEVR_handles
是什么,如果t
是浮点数并且x
是向量?
calcEVR_handles
(对我来说)看起来像一个单元格数组,其中每个元素都是函数的句柄.每个元素calcEVR_handles
都是一个匿名函数,它接受一个值t
和一个向量x
.因此,通过这样做calcEVR_handles{i}
,您将访问存储在单元阵列中第 i 个元素的相应函数.一旦您有权访问,您就可以将参数传递给此函数,它会为您提供这三个输出.
为了向您展示此工作的示例,请考虑以下与其类似的单元格数组calcEVR_handles
.
calcCellFunc = {@sin, @cos, @tan};
Run Code Online (Sandbox Code Playgroud)
这是一个三元素单元格数组,其中每个元素都是函数的句柄.这@
是MATLAB中的一个特殊字符,表示您正在创建函数句柄.它也用于创建匿名函数,但让我们搁置这个答案.如果您想深入了解更多相关细节,可以在此处阅读更多相关信息.
回到我们把手单元阵列,我们会为把手sin
,cos
和tan
.然后,您可以通过访问所需的函数来迭代单元数组,calcCellFunc{idx}
其中idx
所需的元素位于单元数组中.这最终将为您提供存储在索引中的函数idx
.一旦你这样做,你就可以调用该函数并指定你想要的任何输入(如果不接受任何输入,则指定任何输入).这是一个快速的例子.让我们创建一个随机的5 x 5矩阵,并以此矩阵作为输入运行每个函数.然后,我们将这些输出中的每一个输出并存储到输出单元阵列中的相应插槽中.因此:
rng(123); %// Set seed for reproducibility
M = rand(5);
calcCellFunc = {@sin, @cos, @tan};
out = cell(1, numel(calcCellFunc)); %// To store the results for each function
for idx = 1 : numel(calcCellFunc)
out{idx} = calcCellFunc{idx}(M); %// Get the function, then pass
%// the matrix M to it
end
Run Code Online (Sandbox Code Playgroud)
如果你想弄清楚,你可以将out
语句拆分为:
func = calcCellFunc{idx}; %// Get access to the function
out{idx} = func(M); %// Pass M to this function
Run Code Online (Sandbox Code Playgroud)
如果您是处理/匿名函数的新手,您应该首先使用上面的代码来明确说明MATLAB正在做什么.您首先访问存储在单元格数组中的所需函数,然后将参数传递给此函数.
如果我们显示输出,我们得到:
>> celldisp(out)
out{1} =
0.6415 0.4106 0.3365 0.6728 0.5927
0.2823 0.8309 0.6662 0.1815 0.7509
0.2249 0.6325 0.4246 0.1746 0.6627
0.5238 0.4626 0.0596 0.5069 0.5737
0.6590 0.3821 0.3876 0.5071 0.6612
out{2} =
0.7671 0.9118 0.9417 0.7398 0.8054
0.9593 0.5564 0.7458 0.9834 0.6604
0.9744 0.7745 0.9054 0.9846 0.7489
0.8518 0.8866 0.9982 0.8620 0.8191
0.7522 0.9241 0.9218 0.8619 0.7502
out{3} =
0.8363 0.4503 0.3573 0.9094 0.7359
0.2942 1.4934 0.8932 0.1845 1.1370
0.2308 0.8167 0.4690 0.1773 0.8850
0.6149 0.5218 0.0597 0.5880 0.7004
0.8761 0.4135 0.4205 0.5884 0.8814
Run Code Online (Sandbox Code Playgroud)
输出单元阵列的第一元件具有输出时传递M
到sin
地,第二传递时M
到cos
,并且第三,当你传递M
到tan
.
这种代码编写非常有用,因为如果你想使用相同的输入并将它们提供给许多不同的函数,我们自然会倾向于进行一些复制和粘贴.获取每个函数名称,并为每个函数名称创建一行.每一行都会调用你想要的相应函数,然后是输入参数.这可能变得非常乏味,因此一种聪明的方法是将函数名称作为句柄放入单元格数组中,并编写一个for
循环遍历所有函数的动态循环.您甚至可以cellfun
使用for
循环来探索和转义迭代所有函数句柄,但我会留下让您阅读.通过这种方式,您可以使用非常易于维护的代码,如果要删除不需要运行的函数,只需从单元格数组中删除句柄,而不是向下滚动到调用此函数的行所在的位置,然后将其删除.
这实际上是计算机科学/软件工程中非常常见的技术.实际上,这实际上与所谓的函数指针非常接近.这是MATLAB的廉价方式,但这背后的逻辑基本相同.
另一种有用的方法是,如果您有一个函数,其中一个(或多个!)输入是一个函数,并且您还将此函数的输入指定为此函数的附加参数.这就是所谓的高阶函数.输出将基于使用此输入函数,您为其指定的附加输入和输出基于使用此输入函数和您为此函数指定的输入.
一个很好的例子是fzero
MATLAB中的函数.目标是找到非线性函数的根,第一个参数是您指定的函数的句柄.无论函数是什么,fzero
工作方式背后的基本行为都是相同的.您所要做的就是指定要解决的函数以及您认为该根位置的初始猜测.
总而言之,匿名函数非常有用.
归档时间: |
|
查看次数: |
516 次 |
最近记录: |