使用 bsxfun
通常,代码在 for
循环中编写的原因是计算附近代码中的值。功能 bsxfun
通常可用于以更简洁的方式执行此操作。
例如,假设你希望对矩阵 B
执行逐列运算,从中减去每列的平均值:
B = round(randn(5)*10); % Generate random data
A = zeros(size(B)); % Preallocate array
for col = 1:size(B,2); % Loop over columns
A(:,col) = B(:,col) - mean(B(:,col)); % Subtract means
end
如果 B
很大,这种方法效率很低,通常是由于 MATLAB 必须在内存中移动变量的内容。通过使用 bsxfun
,人们可以在一行中整齐,轻松地完成相同的工作:
A = bsxfun(@minus, B, mean(B));
这里,@minus
是一个功能句柄到 minus
操作者(-
)和两个矩阵 B
和 mean(B)
的元件之间的将被应用。其他功能句柄,甚至用户定义的句柄也是可能的。
接下来,假设你要将行向量 v
添加到矩阵 A
中的每一行:
v = [1, 2, 3];
A = [8, 1, 6
3, 5, 7
4, 9, 2];
天真的方法是使用一个循环( 千万不能这样做 ):
B = zeros(3);
for row = 1:3
B(row,:) = A(row,:) + v;
end
另一种办法是复制 v
与 repmat
( 千万不能做到这一点无论 ):
>> v = repmat(v,3,1)
v =
1 2 3
1 2 3
1 2 3
>> B = A + v;
而是使用 bsxfun
执行此任务:
>> B = bsxfun(@plus, A, v);
B =
9 3 9
4 7 10
5 11 5
句法
bsxfun(@fun, A, B)
其中 @fun
是支持的函数之一,两个数组 A
和 B
尊重以下两个条件。
该名 bsxfun
有助于了解函数是如何工作的,它代表了B inary FUN 与 ction S ingletonê X 潘申。换句话说,如果:
- 除了一个,两个数组共享相同的维度
- 并且不一致的维度是两个阵列中的任一个中的单例(即,具有
1
的大小)
那么具有单例维度的数组将被扩展以匹配另一个数组的维度。扩展后,在两个数组上元素应用二元函数。
例如,让 A
成为 M
-by-N
-byK
阵列,B
是 M
-by-N
阵列。首先,它们的前两个尺寸具有相应的尺寸。其次,A
有 K
层,而 B
只隐含 1
,因此它是一个单例。满足所有条件,将复制 B
以匹配 A
的第三维。
在其他语言中,这通常被称为*广播,*并在 Python(numpy)
和 Octave 中自动发生。
函数 @fun
必须是二进制函数,这意味着它必须只有两个输入。
备注
在内部,bsxfun
不会复制数组并执行有效的循环。