使用 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操作者(-)和两个矩阵 Bmean(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

另一种办法是复制 vrepmat千万不能做到这一点无论 ):

>> 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支持的函数之一,两个数组 AB 尊重以下两个条件。

该名 bsxfun 有助于了解函数是如何工作的,它代表了B inary FUN 与 ction S ingletonê X 潘申。换句话说,如果:

  1. 除了一个,两个数组共享相同的维度
  2. 并且不一致的维度是两个阵列中的任一个中的单例(即,具有 1 的大小)

那么具有单例维度的数组将被扩展以匹配另一个数组的维度。扩展后,在两个数组上元素应用二元函数。

例如,让 A 成为 M-by-N-byK 阵列,BM-by-N 阵列。首先,它们的前两个尺寸具有相应的尺寸。其次,AK 层,而 B 只隐含 1,因此它是一个单例。满足所有条件,将复制 B 以匹配 A 的第三维。

在其他语言中,这通常被称为*广播,*并在 Python(numpy) 和 Octave 中自动发生。

函数 @fun 必须是二进制函数,这意味着它必须只有两个输入。

备注

在内部,bsxfun 不会复制数组并执行有效的循环。