MATLAB中[]和[1x0]的区别

22

我在MATLAB中有一个循环,该循环用以下条目填充了我的工作区的一个单元格数组(2011b,Windows 7,64位):

my_array = 
    [1x219 uint16]
    [         138]
    [1x0   uint16] <---- row #3
    [1x2   uint16]
    [1x0   uint16]
    []             <---- row #6
    [         210]
    [1x7   uint16]
    [1x0   uint16]
    [1x4   uint16]
    [1x0   uint16]
    [         280]
    []
    []
    [         293]
    [         295]
    [1x2   uint16]
    [         298]
    [1x0   uint16]
    [1x8   uint16]
    [1x5   uint16]

请注意,有些条目包含[],例如第#6行,而其他条目包含[1x0]项,例如第#3行。

  1. 它们之间是否有任何区别?(除了MATLAB以不同的方式显示它们之外)。在MATLAB中表示它们的方式是否有差异?
  2. 如果差别仅在于MATLAB内部如何表示它们,为什么程序员需要了解此差别?(即为什么要以不同方式显示它们?)这是一个(无害的)软件错误吗?还是了解这样的数组表示方式有任何好处

关于可视化表示的附注:以 [] 显示的变量可以是 uint16 类型,但不一定是。在假设它属于某种数据类型之前,请考虑它是如何创建的或进行检查。 - Dennis Jaheruddin
在这里有关于这个问题的不同答案:https://dev59.com/gL3pa4cB1Zd3GeqPjrWI - Cris Luengo
4个回答

21

大多数情况下(请参见下文的例外情况),两者之间没有真正的区别。由于至少有一个维度具有大小为0,因此两者都被视为“空”。然而,我不会称之为错误,因为作为程序员,在某些情况下你可能希望查看这些信息。

例如,假设你有一个二维矩阵,并且希望索引一些行和列以提取到一个较小的矩阵中:

>> M = magic(4)  %# Create a 4-by-4 matrix

M =
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

>> rowIndex = [1 3];  %# A set of row indices
>> columnIndex = [];  %# A set of column indices, which happen to be empty
>> subM = M(rowIndex,columnIndex)

subM =
   Empty matrix: 2-by-0

请注意,即使结果为空,仍然会告诉您一些信息,具体来说,您尝试从原始矩阵中索引了2行。如果结果仅显示[],则无法确定它是否为空,因为行索引为空还是列索引为空,或者两者都为空。

警告...

有些情况下,定义为空矩阵[](即所有维度均为0)可能会给您带来不同的结果,与某些具有非零维度的空矩阵不同。例如,当处理不同类型的空矩阵时,矩阵乘法可以给您不同(且有些非直观的)结果。让我们考虑这3个空矩阵:

>> a = zeros(1,0);  %# A 1-by-0 empty matrix
>> b = zeros(0,1);  %# A 0-by-1 empty matrix
>> c = [];          %# A 0-by-0 empty matrix

现在,让我们尝试以不同的方式将它们相乘:

>> b*a

ans =
     []  %# We get a 0-by-0 empty matrix. OK, makes sense.

>> a*b

ans =
     0   %# We get a 1-by-1 matrix of zeroes! Wah?!

>> a*c

ans =
   Empty matrix: 1-by-0  %# We get back the same empty matrix as a.

>> c*b

ans =
   Empty matrix: 0-by-1  %# We get back the same empty matrix as b.

>> b*c
??? Error using ==> mtimes
Inner matrix dimensions must agree.  %# The second dimension of the first
                                     %#   argument has to match the first
                                     %#   dimension of the second argument
                                     %#   when multiplying matrices.

两个空矩阵相乘得到非空矩阵似乎让人感到困惑,但实际上这是有道理的,因为结果仍然不包含任何内容(即它的值为0)。


3
+1 实际上,所有这些情况对我来说都有意义。矩阵乘法的定义仍然适用:一个大小为 m×p 的矩阵与一个大小为 p×n 的矩阵相乘得到的是一个大小为 m×n 的矩阵。 - Amro
@gnovice 谢谢你的回答。为什么 a*b=0?在内存中发生了什么? - bokabokaboka

6

在连接矩阵时,公共维度必须匹配。

如果其中一个运算数为空,则当前不会出现错误,但是您将收到一个讨厌的警告,未来版本可能更加严格。

示例:

>> [ones(1,2);zeros(0,9)]
Warning: Concatenation involves an empty array with an incorrect number of columns.
This may not be allowed in a future release. 
ans =
     1     1

>> [ones(2,1),zeros(9,0)]
Warning: Concatenation involves an empty array with an incorrect number of rows.
This may not be allowed in a future release. 
ans =
     1
     1

@Amro:感谢您提供这些示例。 - Ben Voigt

4

另一个区别在于两个版本的empty的内部表示方式。特别是当需要将同一类对象捆绑在数组中时。

假设你有一个虚拟类:

classdef A < handle
%A Summary of this class goes here
%   Detailed explanation goes here

properties
end

methods
end

end

如果您想从空数组开始并将其扩展为A对象的数组:
clear all
clc

% Try to use the default [] for an array of A objects.
my_array = [];
my_array(1) = A;

然后你会得到:
??? The following error occurred converting from A to double:
Error using ==> double
Conversion to double from A is not possible.

Error in ==> main2 at 6
my_array(1) = A;

但是如果您这样做:
% Now try to use the class dependent empty for an array of A objects.
my_array = A.empty;
my_array(1) = A;

那么一切都很好。

我希望这能补充之前给出的解释。


这是使用empty预分配空对象向量的另一个示例:http://stackoverflow.com/questions/6806344/storing-handles-of-objects-generated-by-imline-in-matlab/6807795#6807795 - Amro

0

如果拼接和乘法还不足以让人担忧,那么循环也是个问题。以下是两种观察它们区别的方法:

1. 循环变量大小

for t = 1:size(zeros(0,0),1); % Or simply []
   'no'
end
for t = 1:size(zeros(1,0),1); % Or zeros(0,1)
   'yes'
end

如果你将 size 替换为 length,它会打印出 'yes'。如果不这样做,它将什么都不打印。

如果这不让你惊讶,也许下一个会让你惊讶。

2. 使用 for 循环迭代一个空矩阵

for t = []          %// Iterate an empty 0x0 matrix
    1
end
for t = ones(1, 0)  %// Iterate an empty 1x0 matrix
    2
end
for t = ones(0, 1)  %// Iterate an empty 0x1 matrix
    3
end

将会打印:

ans =
    3

简而言之,对于你的两个问题,我的回答如下:

  • 是的,它们之间肯定存在差异。
  • 实际上,我认为程序员意识到这种差异会受益匪浅,因为这种差异可能会产生意想不到的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接