クラスによる多項式の表現
クラスを使用して新しいデータ型を定義できます。この例は、多項式を表すクラスを実装します。このクラスは多項式の項の係数をベクトルに格納し、多項式を 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 で導入されました。
