Main Content

クラスによる多項式の表現

クラスを使用して新しいデータ型を定義できます。この例は、多項式を表すクラスを実装します。このクラスは多項式の項の係数をベクトルに格納し、多項式を x のべき乗として表示するように既定の MATLAB® 表示をオーバーライドします。また、このクラスでカスタマイズされたインデックスを使用すると、小かっこインデックス構文を使用して x の 1 つ以上の値で多項式を評価できます。

クラス要件

DocPolynom クラスの設計要件は以下のとおりです。

  • 値クラスの動作 — コピーして関数に渡すときに MATLAB 数値変数のように動作します。

  • スカラー オブジェクトの動作 — 多項式オブジェクトは連結できず、多項式配列のサイズは常に (1,1) である必要があります。

  • カスタマイズされたインデックスの動作 — 小かっこインデックス構文を使用して多項式を評価します。p(x) は、オブジェクト p で表される多項式を x の各値で評価します。

  • 表示の特化 — 多項式オブジェクトに格納されている係数を使用して、多項式を代数式として表示します。

  • 加算、減算、および乗算のオーバーライド — 多項式オブジェクトの加算、減算、または乗算により、2 つの多項式の対応する代数演算の結果が返されます。

  • double コンバーター — 多項式オブジェクトを double 配列に変換して、数値入力を受け入れる既存の MATLAB 関数と併用できるようにします。

DocPolynom クラス メンバー

このクラスは、多項式係数を格納するための coef プロパティを定義します。

DocPolynom クラス プロパティ

名前

クラス

既定

説明

coef

double

[]

多項式係数のベクトル (x の指数の降順)。

次の表は、DocPolynom クラスのメソッドをまとめてあります。

DocPolynom クラス メソッド

名前

説明

DocPolynom

クラス コンストラクター

double

DocPolynom オブジェクトを double に変換します。つまり、このメソッドは係数を double 値のベクトルで返します。

char

x のべき乗として DocPolynom オブジェクトの書式付き表示を作成します。このメソッドは disp メソッドで使用されます。

disp

MATLAB が DocPolynom オブジェクトをコマンド ラインにどのように表示するかを定義します。

plus

DocPolynom オブジェクトを加算します。

minus

DocPolynom オブジェクトを減算します。

mtimes

DocPolynom オブジェクトを乗算します。

dispPoly

多項式を 1 つ以上の値について評価し、結果を double 値のベクトルではなく整理されたリストで返します。

parenReference

小かっこインデックス構文を使用した多項式の評価を有効にします。p(x) は、多項式オブジェクト px の各値で評価します。

DocPolynom クラスの使用

次の例は、DocPolynom クラスの基本的な使用方法を示します。f(x) = x3 − 2x − 5 および f(x) = 2x4 + 3x2 + 2x − 7 を表す DocPolynom オブジェクトを作成します。

p1 = DocPolynom([1 0 -2 -5])
p1 =
   x^3 - 2*x - 5
p2 = DocPolynom([2 0 3 2 -7])
p2 =
   2*x^4 + 3*x^2 + 2*x - 7

多項式 p1 の根を求めます。オブジェクトの double メソッドを使用して、結果を関数 roots に渡します。

roots(double(p1))
ans =

   2.0946 + 0.0000i
  -1.0473 + 1.1359i
  -1.0473 - 1.1359i

2 つの多項式 p1p2 を加算します。MATLAB は、2 つの DocPolynom オブジェクトを加算するとき、DocPolynom クラスに対して定義された plus メソッドを呼び出します。

p1 + p2
ans = 

2*x^4 + x^3 + 3*x^2 - 12

DocPolynom クラスの概要

クラスのコード説明
classdef DocPolynom < matlab.mixin.Scalar

多項式のデータ型を実装する値クラス。このクラスは matlab.mixin.Scalar から継承しており、スカラー クラスの動作を適用して小かっこインデックスをカスタマイズする機能も提供します。このスーパークラスの詳細については、matlab.mixin.Scalar を参照してください。

   properties
      coef
   end

多項式係数のベクトル。

   methods      
      function obj = DocPolynom(c)
         if nargin > 0
            if isa(c,'DocPolynom')
               obj.coef = c.coef;
            else
               obj.coef = c(:).';
            end
         end
      end 

以下のいずれかを使用してオブジェクトを作成するクラス コンストラクター:

  • 既存の DocPolynom オブジェクト

  • double のベクトル

詳細については、DocPolynom コンストラクターを参照してください。

      function obj = set.coef(obj,val)
         if ~isa(val,'double')
            error('Coefficients must be doubles.')
         end
         ind = find(val(:).'~=0);
         if isempty(ind)
            obj.coef = val;
         else
            obj.coef = val(ind(1):end);
         end
      end

coef プロパティの set メソッド:

  • 係数を double 型に制限

  • 係数ベクトルから先頭のゼロを削除

詳細については、先頭のゼロの削除を参照してください。

      function c = double(obj)
         c = obj.coef;
      end

係数を返して DocPolynom オブジェクトを double に変換します。

詳細については、他のクラスへの DocPolynom オブジェクトの変換を参照してください。

      function str = char(obj)
         if all(obj.coef == 0)
            s = '0';
            str = s;
            return
         else
            d = length(obj.coef) - 1;
            s = cell(1,d);
            ind = 1;
            for a = obj.coef
               if a ~= 0
                  if ind ~= 1
                     if a > 0
                        s(ind) = {' + '};
                        ind = ind + 1;
                     else
                        s(ind) = {' - '};
                        a = -a;
                        ind = ind + 1;
                     end
                  end
                  if a ~= 1 || d == 0
                     if a == -1
                        s(ind) = {'-'};
                        ind = ind + 1;
                     else
                        s(ind) = {num2str(a)};
                        ind = ind + 1;
                        if d > 0
                           s(ind) = {'*'};
                           ind = ind + 1;
                        end
                     end
                  end
                  if d >= 2
                     s(ind) = {['x^' int2str(d)]};
                     ind = ind + 1;
                  elseif d == 1
                     s(ind) = {'x'};
                     ind = ind + 1;
                  end
               end
               d = d - 1;
            end
         end
         str = [s{:}];
      end

DocPolynom オブジェクトを char に変換します。詳細については、他のクラスへの DocPolynom オブジェクトの変換を参照してください。

      function disp(obj)
         c = char(obj);
         if iscell(c)
            disp(['     ' c{:}])
         else
            disp(c)
         end
      end 

関数 disp をオーバーロードします。このメソッドは、オブジェクトを char メソッドの出力として表示します。

詳細については、DocPolynom の disp のオーバーロードを参照してください。

      function dispPoly(obj,x)
         p = char(obj);
         y = zeros(length(x));
         disp(['f(x) = ',p])
         for k = 1:length(x)
            y(k) = polyval(obj.coef,x(k));
            disp(['   f(',num2str(x(k)),') = ',num2str(y(k))])
         end
      end

評価した多項式をフォーマットされた出力で返します。このメソッドは、polyval をループで使用して、独立変数の指定値で多項式を評価します。

詳細については、評価された式の表示を参照してください。

      function r = plus(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         k = length(obj2.coef) - length(obj1.coef);
         zp = zeros(1,k);
         zm = zeros(1,-k);
         r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]);
      end

      function r = minus(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         k = length(obj2.coef) - length(obj1.coef);
         zp = zeros(1,k);
         zm = zeros(1,-k);
         r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]);
      end

      function r = mtimes(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         r = DocPolynom(conv(obj1.coef,obj2.coef));
      end
   end

3 つの算術演算子を定義します。

  • 多項式の加算

  • 多項式の減算

  • 多項式の乗算

このコードの詳細については、算術演算子の定義を参照してください。

演算子の定義についての一般情報は、演算子のオーバーロードを参照してください。

   methods (Access = protected)
        function f = parenReference(obj,indexOp)
            n = cell2mat(indexOp(1).Indices);
            if numel(indexOp) == 1
                f = polyval(obj.coef,n);
            else
                f = polyval(obj.coef,n).(indexOp(2:end));
            end
        end
   end
end

DocPolynom オブジェクトの小かっこの参照をカスタマイズします。この parenReference の実装により、ユーザーは小かっこインデックス構文を使用して多項式を評価できます。p(x) は、オブジェクト p で表される多項式を x の各値について評価します。

詳細については、小かっこインデックスの再定義を参照してください。

 クラス コードの拡張

DocPolynom コンストラクター

DocPolynom クラス コンストラクターは次のとおりです。

function obj = DocPolynom(c)
   if nargin > 0
      if isa(c,'DocPolynom')
         obj.coef = c.coef;
       else
          obj.coef = c(:).';
       end
    end
end

コンストラクターの呼び出しの構文

DocPolynom コンストラクターは 2 つの異なる入力引数を受け入れることができます。

  • 既存の DocPolynom オブジェクト — 既存の DocPolynom オブジェクトを入力引数として指定してコンストラクターを呼び出すと、入力引数と同じ係数をもつ新しい DocPolynom オブジェクトが返されます。関数 isa は、この入力をチェックします。

  • 係数ベクトル — 入力引数が DocPolynom オブジェクトではない場合、このコンストラクターは、値を行ベクトルの形にしてから coef プロパティに割り当てます。

    coef プロパティの set メソッドは、プロパティの値を double に制限します。プロパティの set メソッドの説明は、先頭のゼロの削除を参照してください。

次の例では、DocPolynom コンストラクターへの入力引数としてベクトルを使用しています。

p = DocPolynom([1 0 -2 -5])
p = 
   x^3 - 2*x -5

このステートメントは、DocPolynom クラスのインスタンスを指定した係数で作成します。オブジェクトの表示は、MATLAB 言語構文を使用する等価な多項式を表します。DocPolynom クラスは、dispchar クラスのメソッドを使用してこの表示を行います。

先頭のゼロの削除

DocPolynom クラスにおける多項式は、降べきの順に並んだ係数を含む行ベクトルとして表されます。係数ベクトル内のゼロは、多項式に含まれない項を表します。したがって、先頭のゼロは、多項式を形成する場合に無視できます。実際、DocPolynom クラスのメソッドには、多項式の次数を決めるために係数ベクトルの長さを使うものがあるため、係数ベクトルから先頭のゼロを削除すると、ベクトルの長さが確実に正しい多項式の次数を表すようになります。

DocPolynom クラスは、指定した係数から先頭のゼロを削除するために set メソッドを使用するプロパティにおいて、プロパティ値を設定する前に、係数ベクトルを格納します。

function obj = set.coef(obj,val)
   if ~isa(val,'double')
     error('Coefficients must be doubles.')
   end
   ind = find(val(:).'~=0);
   if isempty(ind)
     obj.coef = val;
   else
      obj.coef = val(ind(1):end);
   end
end

他のクラスへの DocPolynom オブジェクトの変換

DocPolynom クラスは、2 つのメソッドを定義して、DocPolynom オブジェクトを他のクラスに変換します。

  • double — 関数を使って係数に数学演算を実行できるように、double の数値型に変換します。

  • char — コマンド ウィンドウで表示するため、出力の書式設定に使用する文字に変換します。

double コンバーター

DocPolynom クラスの double コンバーター メソッドは、係数ベクトルを返します。

function c = double(obj)
    c = obj.coef;
end

DocPolynom オブジェクト p の場合、double はクラス double のベクトルを返します。

p = DocPolynom([1 0 -2 -5]);
c = double(p)
c =

     1     0    -2    -5

文字コンバーター

char メソッドは、x のべき乗として表示される多項式を表す char ベクトルを返します。返される char ベクトルは構文的に正しい MATLAB 式です。

char メソッドは cell 配列を使用して、表示された多項式を作成する char ベクトルの要素をまとめます。disp メソッドは、表示する DocPolynom オブジェクトを書式化するために char メソッドを使用します。DocPolynom オブジェクトのユーザーが char または disp メソッドを直接呼び出す可能性は高くありませんが、これらのメソッドにより、DocPolynom クラスは MATLAB の他のデータ クラスと同様に動作できるようになります。

DocPolynomdisp のオーバーロード

DocPolynom オブジェクトのより有効な表示を与えるには、このクラスは、クラス定義において disp をオーバーロードします。この disp メソッドは、char メソッドによって多項式のテキスト表現を生成してから表示します。

係数がすべて 0 の場合、char メソッドは cell 配列または文字 '0' を返します。

function disp(obj)
   c = char(obj);
   if iscell(c)
      disp(['     ' c{:}])
   else
      disp(c)
   end
end 

MATLABdisp メソッドを呼び出す場合

次のステートメントは、DocPolynom オブジェクトを作成します。ステートメントの最後にセミコロンがないため、出力結果はオーバーロードされた disp メソッドを使用してコマンド ラインに表示されます。

p = DocPolynom([1 0 -2 -5])
p =
    x^3 - 2*x - 5

評価された式の表示

dispPoly メソッドは、多項式を x の 1 つ以上の値について評価します。このメソッドは x の入力値をループし、coef プロパティを指定した関数 polyval を使用して多項式を評価します。

function dispPoly(obj,x)
   p = char(obj);
   y = zeros(length(x));
   disp(['f(x) = ',p,])
   for k = 1:length(x)
      y(k) = polyval(obj.coef,x(k));
      disp(['   f(',num2str(x(k)),') = ',num2str(y(k))])
    end
end

DocPolynom オブジェクト p を作成します。

p = DocPolynom([1 0 -2 -5])
p = 
   x^3 - 2*x - 5

x の 3 つの値 [3 5 9] で多項式を評価します。このメソッドは、値のベクトルを返すのではなく、関数表記を使用して結果を整理されたリストで表示します。

dispPoly(p,[3 5 9])
f(x) = x^3 - 2*x - 5
   f(3) = 16
   f(5) = 110
   f(9) = 706

算術演算子の定義

DocPolynom クラスは 3 つの算術演算のメソッドを実装します。

メソッドと構文

演算

plus(a,b)

加算

minus(a,b)

減算

mtimes(a,b)

行列乗算

オーバーロードされた plusminus、および mtimes メソッドは、少なくとも 1 つの DocPolynom オブジェクトを含む引数のペアを受け入れます。

+ 演算子の定義

p または qDocPolynom オブジェクトである場合、次の式は、他方のオブジェクトがより高い優先順位をもつのでなければ、DocPolynom で定義された plus メソッドのオーバーロードの呼び出しを生成します。

p + q

次のメソッドは DocPolynom クラスの plus (+) 演算子をオーバーロードします。

function r = plus(obj1,obj2)
   obj1 = DocPolynom(obj1);
   obj2 = DocPolynom(obj2);
   k = length(obj2.coef) - length(obj1.coef);
   zp = zeros(1,k);
   zm = zeros(1,-k);
   r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]);
end 

plus メソッドによって以下のアクションが実行されます。

  • 確実に両方の入力引数を DocPolynom オブジェクトにして、DocPolynomdouble を含む式が正しく動作するようにします。

  • 2 つの係数ベクトルにアクセスし、必要な場合、一方にゼロを付加して両方を同じ長さにします。実際の加算は、2 つの係数ベクトルのベクトル和です。

  • DocPolynom コンストラクターを呼び出して、適切な型のオブジェクトを多項式の加算結果として作成します。

- 演算子の定義

minus 演算子 (-) では plus (+) 演算子と同じ方法を使用します。minus メソッドは p - q を計算します。優先引数は DocPolynom オブジェクトでなければなりません。

function r = minus(obj1,obj2)
   obj1 = DocPolynom(obj1);
   obj2 = DocPolynom(obj2);
   k = length(obj2.coef) - length(obj1.coef);
   zp = zeros(1,k);
   zm = zeros(1,-k);
   r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]);
end 

* 演算子の定義

mtimes メソッドは積 p*q を計算します。2 つの多項式の乗算は、それらの係数ベクトルの畳み込み (conv) であるため、mtimes メソッドは "行列" の乗算を実装します。

methods
   function r = mtimes(obj1,obj2)
      obj1 = DocPolynom(obj1);
      obj2 = DocPolynom(obj2);
      r = DocPolynom(conv(obj1.coef,obj2.coef));
   end
end 

算術演算子の使用方法

DocPolynom オブジェクトを作成します。

p = DocPolynom([1 0 -2 -5]);

次の 2 つの算術演算は、DocPolynomplusmtimes メソッドを呼び出します。

q = p + 1
r = p*q
q = 
    x^3 - 2*x - 4

r =
    x^6 - 4*x^4 - 9*x^3 + 4*x^2 + 18*x + 20

小かっこインデックスの再定義

DocPolynom クラスは matlab.mixin.Scalar から継承しており、これはモジュール インデックス クラス matlab.mixin.indexing.RedefinesParen から継承します。RedefinesParenparenReference メソッドをオーバーロードすると、ユーザーは小かっこインデックス構文を使用して DocPolynom オブジェクトで表される多項式を評価できます。

たとえば、DocPolynom オブジェクト p を作成します。

p = DocPolynom([1 0 -2 -5])
p =
    x^3 - 2*x - 5

オーバーロードされた parenReference メソッドは、次のコマンドを使用して x = 3x = 4 で多項式の値を評価します。

p([3 4])
ans =
    16   51

モジュール インデックスの実装の詳細

parenReference メソッドは p(x) 形式の式を処理します。ここで、pDocPolynom オブジェクトで、x には数値入力が含まれます。ただし、parenReference は従来の MATLAB インデックス演算ではなく polyval を使用して、coef プロパティに格納されている係数を使用して多項式を評価します。

methods (Access = protected)
    function f = parenReference(obj,indexOp)
       n = cell2mat(indexOp(1).Indices);
       if numel(indexOp) == 1
          f = polyval(obj.coef,n);
       else
          f = polyval(obj.coef,n).(indexOp(2:end));
       end
    end
end

このメソッドによって以下の手順が実行されます。

  1. matlab.indexing.IndexingOperation クラスのインスタンスである indexOp からインデックス値を抽出します。indexOp オブジェクトはそれを cell 配列として格納し、このメソッドはそれを数値配列に変換して n に格納します。

  2. 式内のインデックス演算数を計算します。

  3. n の値で多項式を評価します。この構文の用途には、1 つの小かっこインデックス演算が含まれます。

  4. メソッドが複数のインデックス演算を検出した場合は、polyval を使用して多項式を評価し、転送構文 .(indexOp(2:end)) を使用して残りのインデックス演算を MATLAB に転送します。このクラスではカスタマイズされた追加のインデックス演算はサポートされないため、MATLAB はエラーを返します。

    たとえば、多項式オブジェクトを評価しながら、同時にドット インデックスを使用してその coef プロパティにアクセスしようとすると、エラーが発生します。

    p(5).coef(1)
    Dot indexing is not supported for variables of this type.
    モジュール インデックスを使用した演算の転送の詳細については、Forward Indexing Operationsを参照してください。

この方法でモジュール インデックス クラスを使用すると、小かっこの参照演算のみがカスタマイズされます。プロパティやメソッドへのドット アクセスは影響を受けず、想定どおりに MATLAB によって処理されます。

メモ

matlab.mixin.Scalarmatlab.mixin.indexing.RedefinesParen の機能は R2021b で導入されました。