matlab类中的向量化
Posted
技术标签:
【中文标题】matlab类中的向量化【英文标题】:vectorization in matlab class 【发布时间】:2014-07-06 18:07:17 【问题描述】:我在 MATLAB 中有一个表示虚数的类。我有一个构造函数和两个数据成员:real
和 imag
。我在一个类中使用重载运算符,我想让它与矩阵一起使用:
function obj = plus(o1, o2)
if (any(size(o1) ~= size(o2)))
error('dimensions must match');
end
[n,m] = size(o1);
obj(n,m) = mycomplex();
for i=1:n
for j=1:m
obj(i,j).real = o1(i,j).real + o2(i,j).real;
obj(i,j).imag = o1(i,j).imag + o2(i,j).imag;
end
end
end
但我不想使用 for 循环。我想做类似的事情:
[obj.real] = [o1.real] + [o2.real]
但我不明白为什么它不起作用......错误说:
“错误 + 输出参数过多”。
我知道在 MATLAB 中最好避免 for 循环以加快速度...有人可以解释一下为什么这不起作用,以及在 MATLAB 中考虑向量化的正确方法以及我的函数示例吗?
提前致谢。
编辑:我的复杂类的定义:
classdef mycomplex < handle & matlab.mixin.CustomDisplay
properties (Access = public)
real;
imag;
end
methods (Access = public)
function this = mycomplex(varargin)
switch (nargin)
case 0
this.real = 0;
this.imag = 0;
case 1
this.real = varargin1;
this.imag = 0;
case 2
this.real = varargin1;
this.imag = varargin2;
otherwise
error('Can''t have more than two arguments');
end
obj = this;
end
end
end
【问题讨论】:
您是否有理由不使用对复数的内置支持? 不,这只是为了练习。 这与常规的 MATLAB 结构非常相似,所以这里有一些相关的问题:Matlab: Assigning same value to field in struct array, Updating one field in every element of a Matlab struct array 【参考方案1】:考虑下面的实现。首先是一些注意事项:
可以不带参数调用构造函数。这对于允许preallocating object arrays: obj(m,n) = MyComplex()
为方便起见,构造函数接受数组参数的任一标量。所以我们可以拨打:c_scalar = MyComplex(1,1)
或c_array = MyComplex(rand(3,1), rand(3,1))
plus
运算符现在使用 for 循环(我们稍后会更改它)。
(请注意,我在代码中跳过了一些验证,例如检查 o1
和 o2
的大小是否相同,构造函数中的 a
和 b
也是如此)。
classdef MyComplex < handle
properties
real
imag
end
methods
function obj = MyComplex(a,b)
% default values
if nargin < 2, b = 0; end
if nargin < 1, a = 0; end
% accepts scalar/array inputs
if isscalar(a) && isscalar(b)
obj.real = a;
obj.imag = b;
else
[m,n] = size(a);
obj(m,n) = MyComplex();
for i=1:m*n
obj(i).real = a(i);
obj(i).imag = b(i);
end
end
end
function obj = plus(o1, o2)
[m,n] = size(o1);
obj(m,n) = MyComplex(); % preallocate object array
for i=1:m*n % linear indexing
obj(i).real = o1(i).real + o2(i).real;
obj(i).imag = o1(i).imag + o2(i).imag;
end
end
end
end
一个使用类的例子:
% scalar objects
>> c1 = MyComplex(1,2);
>> c2 = MyComplex(3,4);
>> c3 = c1 + c2
c3 =
MyComplex with properties:
real: 4
imag: 6
% array of objects
>> c4 = [c1;c1] + [c2;c2]
c4 =
2x1 MyComplex array with properties:
real
imag
现在这里是plus
方法的矢量化版本:
function obj = plus(o1, o2)
[m,n] = size(o1);
obj(m,n) = MyComplex();
x = num2cell([o1.real] + [o2.real]);
[obj.real] = deal(x:);
x = num2cell([o1.imag] + [o2.imag]);
[obj.imag] = deal(x:);
end
我使用语法:[objarray.propName]
来引用对象数组中的属性,这会将值作为向量返回。
与在对象数组中分配属性相反,我使用comma-separated lists,因此我必须转换为元胞数组以获得x:
方便的语法。
请注意,deal
调用并不是严格需要的,我们可以在没有它的情况下编写赋值:
[obj.real] = x:;
【讨论】:
感谢 Amro!但为什么我应该使用你的构造函数而不是我的构造函数?另外,我不明白构造函数中的for循环,a是实部,b是虚部,即使它们是矩阵?? 另外,还有其他方法可以实现这种矢量化吗?【参考方案2】:obj(n,m) = mycomplex()
这行看起来很可疑。我想你想在那里做的是obj = mycomplex(n,m)
。
我看不到您的其余代码,但对我来说,这行代码能正常工作真是太神奇了。我怀疑您已经在某处存储了一个obj
变量,而这段代码只是覆盖了该变量的一个条目。我预测如果你清除所有变量,那一行就会失败。
同样,如果不知道 mycomplex()
实际做了什么,就很难理解会发生什么。
【讨论】:
该行似乎设置了变量的类型,并预分配了它。所有内容都在循环内分配。 我发布了 mycomplex 的定义。该行只是预先分配了一个矩阵,该矩阵在矩阵的每个元素中都包含一个 mycomplex 对象。 @BenVoigt 是的,但我不想使用 for 循环... @Phonon:这是预分配对象数组的一种方法,它完全有效:mathworks.com/help/matlab/matlab_oop/…以上是关于matlab类中的向量化的主要内容,如果未能解决你的问题,请参考以下文章