角落案例,意外和不寻常的MATLAB

时间:2009-11-10 18:51:41

标签: matlab

多年来,在阅读其他代码时,我遇到并收集了一些MATLAB语法的例子,这些例子最初可能是不寻常的,违反直觉的。请随时评论或补充此列表。我用r2006a验证了它。


MATLAB 总是将函数的第一个输出参数(如果它至少有一个)返回到其调用者工作空间中,如果调用函数而没有返回调用者myFunc1(); myFunc2();之类的参数,也会意外地返回工作空间仍将包含myFunc2();的第一个输出作为“不可见”ans变量。如果ans是参考对象,它可以发挥重要作用 - 它将保持活着。


set([], 'Background:Color','red')

MATLAB有时很宽容。在这种情况下,将属性设置为对象数组也可以使用无意义属性,至少在数组为空时。此类数组通常来自harray = findobj(0,'Tag','NotExistingTag')


myArray([1,round(end/2)])

end关键字的使用可能看起来不干净,但有时非常方便,而不是使用length(myArray)


any([]) ~= all([])

令人惊讶地any([])返回falseall([])返回true。我一直认为allany强。

修改

非空参数all()true返回any()的值的子集返回true(例如真值表)。这意味着any() false隐含all() false。 MATLAB违反了这个简单的规则,[]为参数。

Loren也blogged about it


Select(Range(ExcelComObj))

程序样式COM对象方法调度。不要怀疑exist('Select')返回零!


[myString, myCell]

在这种情况下,MATLAB将字符串变量myString隐式转换为单元格类型{myString}。它也有效,如果我不希望它这样做的话。


[double(1.8), uint8(123)] => 2 123

另一个演员的例子。每个人都可能希望将uint8值转换为double,但Mathworks还有另一种意见。没有警告,这种行为非常危险。


a = 5;
b = a();

看起来很傻但你可以用圆括号调用变量。实际上它是有道理的,因为这样你可以在给定句柄的情况下执行一个函数。


语法Foo(:)不仅可以处理数据,还可以作为Bar.Foo(:)调用函数,在这种情况下,函数输入参数作为char 冒号 {{1}传递}。

例如,让':' 现在调用Bar.Foo = @(x) disp(x)在MATLAB命令窗口中打印char Bar.Foo(:)

这个奇怪的功能适用于所有没有警告的MATLAB 7版本。


':'

这个代码既不会返回一个向量,也不会产生错误,但只使用代码布局来定义矩阵。这可能是远古时代的遗物。

编辑:非常方便的功能,请参阅gnovice的评论。


a = {'aa', 'bb'
'cc', 'dd'};

此代码执行您可能期望它执行的操作。该函数set(hobj, {'BackgroundColor','ForegroundColor'},{'red','blue'}) 接受一个结构,因为它的第二个参数是一个已知的事实并且有意义,并且这个sintax只是set的距离。


首先,等值规则有时会出乎意料。例如cell2struct返回true(尽管对于C-experts来说这是不言而喻的)。同样,'A'==65按预期返回,isequal([],{})false会返回isequal([],'')

字符串数字等价意味着所有字符串函数也可以用于数值数组,例如查找大数组中子数组的索引:

true

MATLAB函数ind = strfind( [1 2 3 4 1 2 3 4 1 2 3 4 ], [2 3] ) 为布尔值返回isnumeric()。这感觉只是......假: - )


您了解哪些其他意外/异常的MATLAB功能?

3 个答案:

答案 0 :(得分:12)

图像坐标与情节坐标每次都让我来。

%# create an image with one white pixel
img = zeros(100);
img(25,65) = 1;

%# show the image
figure
imshow(img);

%# now circle the pixel. To be sure of the coordinate, let's run find
[x,y] = find(img);
hold on
%# plot a red circle...
plot(x,y,'or')
%# ... and it's not in the right place

%# plot a green circle with x,y switched, and it works
plot(y,x,'og')

编辑1

数组维度

变量至少有两个维度。标量大小为[1,1],向量的大小为[1,n][n,1]。因此,ndims为其中任何一个返回2(事实上,ndims([])也是2,因为size([])[0,0])。这使得测试输入的维数变得有点麻烦。要检查1D数组,必须使用isvector,0D数组需要isscalar

编辑2

数组作业

通常,Matlab对数组赋值很严格。例如

m = magic(3);
m(1:2,1:3) = zeros(3,2);

抛出一个

??? Subscripted assignment dimension mismatch.

然而,这些工作:

m(1:2,1:2) = 1; %# scalar to vector
m(2,:) = ones(3,1); %# vector n-by-1 to vector 1-by-n (for newer Matlab versions)
m(:) = 1:9; %# vector to 'linearized array'

编辑3

使用错误大小的数组进行逻辑索引祝你好运调试!

逻辑索引似乎调用了find,因为你的逻辑数组不需要与索引相同数量的元素!

>> m = magic(4); %# a 4-by-4 array
>> id = logical([1 1 0 1 0])
id =
     1     1     0     1     0
>> m(id,:)  %# id has five elements, m only four rows
ans =
    16     2     3    13
     5    11    10     8
     4    14    15     1
%# this wouldn't work if the last element of id was 1, btw

>> id = logical([1 1 0])
id =
     1     1     0
>> m(id,:) %# id has three elements, m has four rows
ans =
    16     2     3    13
     5    11    10     8

答案 1 :(得分:8)

我不会列出奇怪的MATLAB语法示例,而是会解决我认为有意义或预期/记录/期望行为的问题中的一些示例。

  • ANYALL如何处理空参数:

    any([])的结果是有意义的:输入向量中没有非零元素(因为它是空的),所以它返回false。

    通过考虑如何实现自己的此函数版本,可以更好地理解all([])的结果:

    function allAreTrue = my_all(inArray)
      allAreTrue = true;
      N = numel(inArray);
      index = 1;
      while allAreTrue && (index <= N)
        allAreTrue = (inArray(index) ~= 0);
        index = index + 1;
      end
    end
    

    此函数循环遍历inArray的元素,直到遇到零值。如果inArray为空,则永远不会输入循环,并返回默认值allAreTrue

  • 与类不同的连接:

    当将不同类型连接成一个数组时,MATLAB遵循preset precedence of classes并相应地转换值。一般优先顺序(从最高到最低)是:charinteger(任何符号或位数),singledouble和{{1} }。这就是logical为您提供[double(1.8), uint8(123)]类型结果的原因。当组合不同于整数类型(uint8uint8等)时,left-most matrix element determines the type of the result

  • 不使用line continuation operator (...)的多行:

    构造具有多行的矩阵时,您只需在输入一行后点击返回并在下一行输入下一行,而无需使用semicolon来定义新行或{{1}继续这条线。因此,以下声明是等效的:

    int32

    为什么要让MATLAB表现得像这样?我注意到的一个原因是它可以很容易地将数据从例如Excel文档剪切并粘贴到MATLAB命令窗口中的变量中。请尝试以下方法:

    • 在Excel文件中选择一个区域并进行复制。
    • 在{MATLAB >中键入...,而不会返回
    • 右键单击MATLAB命令窗口并选择“粘贴”。
    • 输入a = {'aa', 'bb' 'cc', 'dd'}; a = {'aa', 'bb'; ... 'cc', 'dd'}; a = {'aa', 'bb'; 'cc', 'dd'}; 并点击返回。现在,您有一个变量a = [,其中包含您在Excel文件中选择的行和列中的数据,并保留数据的“形状”。

答案 2 :(得分:5)

阵列与细胞

让我们先看一下基本语法。要创建包含元素 a b c 的数组,请编写[a b c]。要创建包含数组 A B C 的单元格,请编写{A B C}。到目前为止一切都很好。

访问数组元素的方式如下:arr(i)。对于Cells,它是cell{i}。还是不错的。

现在让我们尝试删除一个元素。对于数组:arr(i) = []。从上面的示例推断,您可以尝试cell{i} = {}单元格,但这是语法错误。实际上,删除单元格元素的正确语法与数组使用的语法完全相同:cell(i) = []

因此,大多数情况下您使用特殊语法访问单元格,但在删除项目时使用数组语法。

如果你深入挖掘,你会发现实际上一个单元格是一个数组,其中每个值都是某种类型。所以你仍然可以写cell(i),你只需要获得{A}(一个单值的单元格!)。 cell{i}是直接检索A的简写。

这一切都不是很漂亮的IMO。