我在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 = varargin{1};
this.imag = 0;
case 2
this.real = varargin{1};
this.imag = varargin{2};
otherwise
error('Can''t have more than two arguments');
end
obj = this;
end
end
end
考虑下面的实现。首先是注意事项:
-
构造函数可以不带参数调用。这对于允许预分配对象数组很重要:
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]
来引用对象数组中的属性,这将返回值作为向量。
与在对象数组中分配属性相反,我使用逗号分隔的列表,因此我必须转换为单元格数组以获得x{:}
方便的语法。
注意,deal
调用不是严格需要的,我们可以不使用它来写赋值:
[obj.real] = x{:};
obj(n,m) = mycomplex()
行看起来很可疑。我觉得你应该用obj = mycomplex(n,m)
代替。
我看不到你剩下的代码,但对我来说,这一行居然能正常工作真是不可思议。我怀疑您已经在某个地方存储了一个obj
变量,而这段代码只是覆盖了该变量的一个条目。我预测如果您清除所有变量,它将在那一行失败。
如果不知道mycomplex()
的实际作用,就很难理解发生了什么。