1

我在 MATLAB 中有一个代表虚数的类。我有一个构造函数和两个数据成员:realimag. 我在一个类中使用重载运算符,我想让它与矩阵一起工作:

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
4

2 回答 2

2

考虑下面的实现。首先一些注意事项:

  • 可以不带参数调用构造函数。这对于允许预分配对象数组很重要:obj(m,n) = MyComplex()

  • 为方便起见,构造函数接受数组参数的任一标量。所以我们可以调用:c_scalar = MyComplex(1,1)c_array = MyComplex(rand(3,1), rand(3,1))

  • 操作员plus现在使用 for 循环(我们稍后将更改它)。

(请注意,我在代码中跳过了一些验证,例如检查o1o2大小相同,类似地 forab在构造函数中)。

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{:};
于 2014-07-06T20:56:03.020 回答
0

这条线obj(n,m) = mycomplex()看起来很可疑。我认为你想要做的是obj = mycomplex(n,m)

我看不到你的代码的其余部分,但对我来说,这条线甚至可以工作,这对我来说很神奇。我怀疑您已经在obj某处存储了一个变量,而这段代码只是覆盖了该变量的一个条目。我预测,如果您清除所有变量,它将在那条线上失败。

同样,如果不知道实际发生了什么,就很难理解发生了什么mycomplex()

于 2014-07-06T18:32:43.167 回答