1

虚数を表す MATLAB のクラスがあります。コンストラクターと 2 つのデータ メンバーがあります: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が同じサイズであることを確認するなど、コンストラクターの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{:};
于 2014-07-06T20:56:03.020 に答える
0

obj(n,m) = mycomplex()は非常に疑わしいようです。あなたがそこでやりたいことはobj = mycomplex(n,m)代わりだと思います。

コードの残りの部分は見えませんが、この行が機能していることは奇跡的です。すでにどこかに変数が保存されているのではないかと思いますが、objこのコードはその変数の 1 つのエントリを上書きするだけです。すべての変数をクリアすると、その行で失敗すると予測しています。

繰り返しますが、実際に何が行われるかを知らずに何が起こるかを理解することは非常に困難mycomplex()です。

于 2014-07-06T18:32:43.167 に答える