如何建立一个匿名函数,以采取矢量输入在八度?



我想定义一个接受一个向量的匿名函数,但是除非指定向量中的每个元素,否则我无法实现这一点:

Data = 
[ X11 X12;
X21 X22];

迭代#1:V -> [X11 X12](在每次迭代时传递给'some_func'的期望行值)。迭代#2:V -> [X21 X22]

如此:

good_func_handle = @(a1,a2)  some_func([a1,a2],bla,bla)
output = arrayfun(good_func_handle,Data(:,1),Data(:,2)) -> to avoid having to write a for loop

这行不通:

bad_func_handle = @(vec)  some_func(vec,bla,bla)
output = arrayfun(bad_func_handle,Data)

当调用时,只有第一个元素X11被传递给some_func,而不是X11X12

是否有一种方法可以将函数设置为将向量变量作为输入,而不必指定向量中的所有元素?

问题是在arrayfun,而不是在被调用的函数。arrayfun循环遍历输入数组的每个元素,而不是每一行。在第一个解决方案中,您创建了输入数组,这样循环遍历每个元素是正确的。

由于arrayfun只是一个循环,除了程序员的时间外,使用它在时间上没有任何优势。它只是为了简化在数组上编写循环。(资格:在MATLAB中,arrayfun增加了开销,因为每次迭代都需要调用函数;这可能非常重要,如下所示。在Octave中,arrayfun似乎比普通循环更有效,参见下面smcmi的注释。[/p]


为了回应@smcmi下面的评论,我重新创建了他们的实验如下:

a = zeros(1, 1e6);
b = method1(a);
c = method2(a);
assert(isequal(b,c))
timeit(@()method1(a))
timeit(@()method2(a))
function out = method1(in)
out = zeros(size(in));
for ii=1:numel(in)
out(ii) = in(ii) * 2;
end
end
function out = method2(in)
out = arrayfun(@(x) x * 2, in);
end

使用MATLAB Online运行此程序(通常非常慢),我看到以下输出:

ans =
0.0036
ans =
2.5299

也就是说,普通循环需要0.0036秒,而arrayfun需要2.5秒。这是三个数量级的差别。

arrayfun中最大的开销是为每个数组元素调用一个函数。在MATLAB中,调用函数仍然会带来一些开销,而JIT完全优化了循环,并且运行速度与任何编译语言相似。

在Octave中,计时是完全不同的,因为它根本没有JIT。有关八度音阶性能,请参阅下面的评论。

最新更新