クラスによる多項式の表現
クラスを使用して新しいデータ型を定義できます。この例は、多項式を表すクラスを実装します。このクラスは多項式の項の係数をベクトルに格納し、多項式を x のべき乗として表示するように既定の MATLAB® 表示をオーバーライドします。また、このクラスでカスタマイズされたインデックスを使用すると、小かっこインデックス構文を使用して x の 1 つ以上の値で多項式を評価できます。
クラス要件
DocPolynom
クラスの設計要件は以下のとおりです。
値クラスの動作 — コピーして関数に渡すときに MATLAB 数値変数のように動作します。
スカラー オブジェクトの動作 — 多項式オブジェクトは連結できず、多項式配列のサイズは常に (1,1) である必要があります。
カスタマイズされたインデックスの動作 — 小かっこインデックス構文を使用して多項式を評価します。
p(x)
は、オブジェクトp
で表される多項式をx
の各値で評価します。表示の特化 — 多項式オブジェクトに格納されている係数を使用して、多項式を代数式として表示します。
加算、減算、および乗算のオーバーライド — 多項式オブジェクトの加算、減算、または乗算により、2 つの多項式の対応する代数演算の結果が返されます。
double コンバーター — 多項式オブジェクトを
double
配列に変換して、数値入力を受け入れる既存の MATLAB 関数と併用できるようにします。
DocPolynom
クラス メンバー
このクラスは、多項式係数を格納するための coef
プロパティを定義します。
DocPolynom
クラス プロパティ
名前 | クラス | 既定 | 説明 |
---|---|---|---|
|
|
| 多項式係数のベクトル (x の指数の降順)。 |
次の表は、DocPolynom
クラスのメソッドをまとめてあります。
DocPolynom
クラス メソッド
名前 | 説明 |
---|---|
| クラス コンストラクター |
|
|
|
|
| MATLAB が |
|
|
|
|
|
|
| 多項式を 1 つ以上の値について評価し、結果を |
| 小かっこインデックス構文を使用した多項式の評価を有効にします。 |
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 つの多項式 p1
と p2
を加算します。MATLAB は、2 つの DocPolynom
オブジェクトを加算するとき、DocPolynom
クラスに対して定義された plus
メソッドを呼び出します。
p1 + p2
ans = 2*x^4 + x^3 + 3*x^2 - 12
DocPolynom
クラスの概要
クラスのコード | 説明 |
---|---|
classdef DocPolynom < 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 コンストラクターを参照してください。 |
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 |
詳細については、先頭のゼロの削除を参照してください。 |
function c = double(obj) c = obj.coef; end | 係数を返して 詳細については、他のクラスへの 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 |
|
function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end | 関数 詳細については、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 | 評価した多項式をフォーマットされた出力で返します。このメソッドは、 詳細については、評価された式の表示を参照してください。 |
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
コンストラクター
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
クラスは、disp
と char
クラスのメソッドを使用してこの表示を行います。
先頭のゼロの削除
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 の他のデータ クラスと同様に動作できるようになります。
DocPolynom
の disp
のオーバーロード
DocPolynom
オブジェクトのより有効な表示を与えるには、このクラスは、クラス定義において disp
をオーバーロードします。この disp
メソッドは、char
メソッドによって多項式のテキスト表現を生成してから表示します。
係数がすべて 0 の場合、char
メソッドは cell 配列または文字 '0'
を返します。
function disp(obj) c = char(obj); if iscell(c) disp([' ' c{:}]) else disp(c) end end
MATLAB が disp
メソッドを呼び出す場合
次のステートメントは、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
、minus
、および mtimes
メソッドは、少なくとも 1 つの DocPolynom
オブジェクトを含む引数のペアを受け入れます。
+
演算子の定義
p
または q
が DocPolynom
オブジェクトである場合、次の式は、他方のオブジェクトがより高い優先順位をもつのでなければ、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
オブジェクトにして、DocPolynom
とdouble
を含む式が正しく動作するようにします。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 つの算術演算は、DocPolynom
の plus
と mtimes
メソッドを呼び出します。
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
から継承します。RedefinesParen
の parenReference
メソッドをオーバーロードすると、ユーザーは小かっこインデックス構文を使用して DocPolynom
オブジェクトで表される多項式を評価できます。
たとえば、DocPolynom
オブジェクト p
を作成します。
p = DocPolynom([1 0 -2 -5])
p = x^3 - 2*x - 5
オーバーロードされた parenReference
メソッドは、次のコマンドを使用して x = 3
と x = 4
で多項式の値を評価します。
p([3 4])
ans = 16 51
モジュール インデックスの実装の詳細
parenReference
メソッドは p(x)
形式の式を処理します。ここで、p
は DocPolynom
オブジェクトで、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
このメソッドによって以下の手順が実行されます。
matlab.indexing.IndexingOperation
クラスのインスタンスであるindexOp
からインデックス値を抽出します。indexOp
オブジェクトはそれを cell 配列として格納し、このメソッドはそれを数値配列に変換してn
に格納します。式内のインデックス演算数を計算します。
n
の値で多項式を評価します。この構文の用途には、1 つの小かっこインデックス演算が含まれます。メソッドが複数のインデックス演算を検出した場合は、
polyval
を使用して多項式を評価し、転送構文.(indexOp(2:end))
を使用して残りのインデックス演算を MATLAB に転送します。このクラスではカスタマイズされた追加のインデックス演算はサポートされないため、MATLAB はエラーを返します。たとえば、多項式オブジェクトを評価しながら、同時にドット インデックスを使用してその
coef
プロパティにアクセスしようとすると、エラーが発生します。p(5).coef(1)
モジュール インデックスを使用した演算の転送の詳細については、Forward Indexing Operationsを参照してください。Dot indexing is not supported for variables of this type.
この方法でモジュール インデックス クラスを使用すると、小かっこの参照演算のみがカスタマイズされます。プロパティやメソッドへのドット アクセスは影響を受けず、想定どおりに MATLAB によって処理されます。
メモ
matlab.mixin.Scalar
と matlab.mixin.indexing.RedefinesParen
の機能は R2021b で導入されました。