多年来,在阅读其他代码时,我遇到并收集了一些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([])
返回false
,all([])
返回true
。我一直认为all
比any
强。
修改
非空参数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功能?
答案 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语法示例,而是会解决我认为有意义或预期/记录/期望行为的问题中的一些示例。
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并相应地转换值。一般优先顺序(从最高到最低)是:char
,integer
(任何符号或位数),single
,double
和{{1} }。这就是logical
为您提供[double(1.8), uint8(123)]
类型结果的原因。当组合不同于整数类型(uint8
,uint8
等)时,left-most matrix element determines the type of the result。
不使用line continuation operator (...
)的多行:
构造具有多行的矩阵时,您只需在输入一行后点击返回并在下一行输入下一行,而无需使用semicolon来定义新行或{{1}继续这条线。因此,以下声明是等效的:
int32
为什么要让MATLAB表现得像这样?我注意到的一个原因是它可以很容易地将数据从例如Excel文档剪切并粘贴到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。