Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

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

オブジェクトの要件

この例は、多項式を表すクラスを MATLAB® 言語で実装します。設計要件は以下のとおりです。

  • 値クラスの動作 - 多項式オブジェクトは、コピーして関数に渡すときに MATLAB 数値変数のように動作します。

  • 表示とインデックスの特化

  • オブジェクトはスカラーのみです。表示とインデックス機能の特化により通常の配列動作は妨げられます。

  • 算術演算

  • 数値入力を受け入れる既存の MATLAB 関数と多項式オブジェクトとの併用を簡略化する double コンバーター

DocPolynom クラス メンバー

クラスの定義は、データを保存するためのプロパティを指定し、クラスの定義を含めるフォルダー (@DocPolynom) を定義します。

次の表は、DocPolynom クラスに対して定義されるプロパティをまとめてあります。

DocPolynom クラス プロパティ

名前

クラス

既定

説明

coef

double

[]

多項式係数のベクトル [最高次数 ... 最低次数]

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

DocPolynom クラス メソッド

名前

説明

DocPolynom

クラス コンストラクター

double

DocPolynom オブジェクトを double に変換します (係数をベクトルで返します)

char

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

disp

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

subsref

独立変数の値を添字として指定できます。また、ドット表記で coef プロパティにアクセスしたり、メソッドを呼び出すことができます。

plus

DocPolynom オブジェクトの加算を実装します

minus

DocPolynom オブジェクトの減算を実装します

mtimes

DocPolynom オブジェクトの乗算を実装します

DocPolynom クラスの使用

次の例は、DocPolynom クラスの基本的な使用方法を示します。

次の多項式を表す 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

係数を関数 roots に渡すことにより、多項式の根を検出します。

roots(p1.coef)
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

多項式のデータ型を実装する値クラス。

   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 コンストラクターを参照してください。

      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(ind(1):end);
         else
            obj.coef = val;
         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 に変換します。

y = f(x)

他のタイプへの 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);
         e = @(x)eval(p);
         y = zeros(length(x));
         disp(['y = ',p])
         for k = 1:length(x)
            y(k) = e(x(k));
            disp(['  ',num2str(y(k)),...
                  ' = f(x = ',...
                  num2str(x(k)),')'])
         end
      end

評価した式をフォーマットされた出力で返します。

char メソッドの出力を使用して、独立変数の指定値で多項式を評価します。

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

      function b = subsref(a,s)
         switch s(1).type
            case '()'
               ind = s.subs{:};
               b = polyval(a.coef,ind);
            case '.'
               switch s(1).subs
                  case 'coef'
                     b = a.coef;
                  case 'disp'
                     disp(a)
                  otherwise
                     if length(s)>1
                        b = a.(s(1).subs)(s(2).subs{:});
                     else
                        b = a.(s.subs);
                     end
               end
            otherwise
               error('Specify value for x as obj(x)')
         end
      end

DocPolynom オブジェクトのインデックス付き参照を再定義します。

このコードについての詳細は、インデックス付き参照の再定義を参照してください。

      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 つの算術演算子を定義します。

  • 多項式の加算

  • 多項式の減算

  • 多項式の乗算

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

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

   end
end

methods および classdefend ステートメント。

 クラス コードの拡張

DocPolynom コンストラクター

次の関数は、ファイル @DocPolynom/DocPolynom.m にある、DocPolynom クラスのコンストラクターです。

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

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

2 つの異なる引数で DocPolynom コンストラクターを呼び出すことができます。

  • 入力引数が 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 クラスのメソッドを使用してこの表示を行います。

不要な係数の削除

MATLAB における多項式は、降べき順の係数を含む行ベクトルとして表されます。係数ベクトル内のゼロは、多項式から除く項を表します。したがって、先頭のゼロは、多項式を形成する場合に無視できます。

DocPolynom クラスのメソッドには、多項式の次数を決めるために係数ベクトルの長さを使うものがあります。したがって、係数ベクトルが真の値を表すように、係数ベクトルから先頭のゼロを削除することが有効です。

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

methods
   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(ind(1):end);
      else
         obj.coef = val;
      end
   end
end

他のタイプへの DocPolynom オブジェクトの変換

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

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

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

double コンバーター

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

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

DocPolynom オブジェクト p の場合、

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

ステートメント、

c = double(p)

は、以下を返します。

c=
    1     0    -2    -5

これは、double クラスになります。

class(c)
ans = 
   double

文字コンバーター

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

char メソッドは cell 配列を使用して、表示された多項式を作成する char ベクトルの要素をまとめます。

disp メソッドは、表示する DocPolynom オブジェクトを書式化するために char メソッドを使用します。evalPoly メソッドは char を使用して、評価する MATLAB 式を作成します。

DocPolynom オブジェクトのユーザーが char または disp メソッドを直接呼び出す可能性は高くありませんが、これらのメソッドにより、DocPolynom クラスは MATLAB の他のデータ クラスと同様に動作できるようになります。

以下は、char メソッドです。

methods
   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
end

DocPolynom の disp のオーバーロード

DocPolynom オブジェクトのより有効な表示を与えるには、このクラスは、クラス定義において disp をオーバーロードします。

この disp メソッドは、char メソッドによって、多項式のテキスト表現を画面上に表示します。

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

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

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

次のステートメント

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

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

p =
    x^3 - 2*x - 5

評価された式の表示

char コンバーター メソッドは、DocPolynom オブジェクトによって表される多項式の MATLAB 式を形成します。dispPoly メソッドは char メソッドによって返される式を、指定された x の値で評価します。

methods
   function dispPoly(obj,x)
      p = char(obj);
      e = @(x)eval(p);
      y = zeros(length(x));
      disp(['y = ',p])
      for k = 1:length(x)
         y(k) = e(x(k));
          disp(['  ',num2str(y(k)),...
               ' = f(x = ',...
               num2str(x(k)),')'])
      end
   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])
y = x^3 - 2*x - 5
  16 = f(x = 3)
  110 = f(x = 5)
  706 = f(x = 9)

インデックス付き参照の再定義

DocPolynom クラスは、多項式を表すオブジェクトの使用をサポートするために、インデックス付き参照を再定義します。DocPolynom クラスでは、オブジェクトへの添字参照によって、添字と等しい独立変数の値による多項式の評価が行われます。

たとえば、次の多項式を与えると、

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

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

次の添字付きの式は、x = 3x = 4 で多項式の値を評価し、結果の値を返します。

p([3 4])
ans =
    16   51

インデックス付き参照の設計目標

subsref メソッドを実装して、既定の添字参照の動作を再定義します。

クラスで subsref メソッドを定義すると、添字付きの参照があるときは必ず、MATLAB はこのクラスのオブジェクトに対してこのメソッドを呼び出します。subsref メソッドは、変更する特定のケースだけでなく、すべてのインデックス付き参照の動作を定義しなければなりません。

DocPolynomsubsref メソッドは、以下の動作を実装します。

  • p(x = [a1...an])x = a で多項式を評価します。

  • p.coefcoef プロパティの値にアクセスします。

  • p.disp — 出力を割り当てずに多項式を MATLAB 式として表示します。

  • obj = p.method(args) — ドット表記を使用して引数と共にメソッドを呼び出し、変更されたオブジェクトを返します。

  • obj = p.method — ドット表記を使用して引数なしでメソッドを呼び出し、変更されたオブジェクトを返します。

subsref 実装の詳細

subsref メソッドは関数 subsref をオーバーロードします。

たとえば、関数 polyval への呼び出しを考えます。

p = DocPolynom([1 0 -2 -5])
p = 
     x^3 - 2*x - 5
polyval(p.coef,[3 5 7])
ans =
    16   110   324

関数 polyval は以下を必要とします。

  • 多項式係数

  • 多項式の評価に使用する独立変数の値

関数 polyval はこうした値における f(x) の値を返します。subsref はステートメントを通して polyval を呼び出します。

case '()'
   ind = s.subs{:};
   b = polyval(a.coef,ind);

ドット表記を使用した引数を伴うメソッド呼び出しをサポートするために subsref を実装する場合、type および subs 構造フィールドのどちらにも複数の要素が含まれます。

subsref メソッドは、以下のコード リストに示されているように、すべての添字参照を明示的に実装します。

methods
   function b = subsref(a,s)
      switch s(1).type
         case '()'
            ind = s.subs{:};
            b = polyval(a.coef,ind);
         case '.'
            switch s(1).subs
               case 'coef'
                  b = a.coef;
               case 'disp'
                  disp(a)
               otherwise
                  if length(s)>1
                     b = a.(s(1).subs)(s(2).subs{:});
                  else
                     b = a.(s.subs);
                  end
            end
         otherwise
            error('Specify value for x as obj(x)')
      end
   end
end

算術演算子の定義

多項式ではいくつかの算術演算が意味をもちます。DocPolynom クラスは次のメソッドを実装します。

メソッドと構文

実装される演算子

plus(a,b)

加算

minus(a,b)

減算

mtimes(a,b)

行列乗算

算術演算子をオーバーロードする場合は、サポートの必要があるデータ型を考慮します。plusminus および mtimes のメソッドは、DocPolynomDocPolynomDocPolynomdouble というオペランドの組み合わせでの加算、減算、乗算を扱うように、DocPolynom クラスに対して定義されます。

+ 演算子の定義

p または qDocPolynom オブジェクトである場合、次の式について考えます。

p + q

この式は、他方のオブジェクトがより高い優先順位をもつのでなければ、関数 @DocPolynom/plus を呼び出します。

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

methods
   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
end 

この関数の機能について説明します。

  • 両方の入力引数を DocPolynom オブジェクトにします。次のような式

    p + 1
    

    は、DocPolynomdouble の両方を含みますが、正しく動作します。

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

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

- 演算子の定義

plus (+) 演算子と同じ方法で、minus 演算子 (-) を実装します。

minus メソッドは p - q を計算します。優先引数は DocPolynom オブジェクトでなければなりません。

methods
   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
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