MATLAB Language
よくある間違いやエラー
サーチ…
既存の関数名で変数名を指定しないでください
すでに関数sum()
ます。その結果、同じ名前の変数に名前を付けると
sum = 1+3;
変数がまだワークスペースに存在している間に関数を使用しようとすると
A = rand(2);
sum(A,1)
私たちは謎のエラーを取得します :
Subscript indices must either be real positive integers or logicals.
最初に変数をclear()
てから関数を使用する
clear sum
sum(A,1)
ans =
1.0826 1.0279
この競合を避けるために関数がすでに存在するかどうかを確認するにはどうすればよいですか?
which()
を-all
フラグとともに使用する:
which sum -all
sum is a variable.
built-in (C:\Program Files\MATLAB\R2016a\toolbox\matlab\datafun\@double\sum) % Shadowed double method
...
この出力は、 sum
が最初に変数であり、次のメソッド(関数)がそれによってシャドーされていることを示しています。つまり、MATLABはまずメソッドを使用するのではなく変数に構文を適用しようとします。
あなたが見るのはあなたが得意なものではありません:コマンドウィンドウのcharとcellstring
新しいユーザーを対象とした基本的な例です。 char
とcellstring
違いを説明することに焦点を合わせません。
それはあなたがそれらを追加したことはありませんが、あなたの文字列で'
を取り除きたい場合があります。実際、それらはコマンドウィンドウがいくつかのタイプを区別するために使用するアーティファクトです。
文字列が印刷されます
s = 'dsadasd'
s =
dsadasd
セルストリングが印刷されます
c = {'dsadasd'};
c =
'dsadasd'
一重引用符とインデントが、 c
がchar
ではなくcellstring
であることを私たちに知らせるためのアーチファクトであることに注意してください。文字列は実際にセルに含まれています。
c{1}
ans =
dsadasd
転置演算子
-
.'
MATLABでベクトルまたは行列を転置する正しい方法です。 -
'
は、MATLABのベクトルまたは行列の複素共役転置 (別名エルミート共役)を取る正しい方法です。
転置については注意してください.'
アポストロフィの前に期間があります。これは、MATLABの他の要素単位の演算のための構文と一致している: *
、 行列を乗算.*
行列の要素を一緒に乗算します。 2つのコマンドは非常に似ていますが、概念的には非常に明確です。他のMATLABコマンドと同様に、これらの演算子は実行時に「適切な」関数呼び出しに変換される「構文的砂糖」です。 ==
がeq関数の評価になるのと同じように.'
transpose
の略語として。 '
(ポイントなしで)書くだけであれば、実際には代わりにctranspose
コマンドを使用しています。これは複素共役転置を計算します。これはエルミート共役としても知られています。転置されたベクトルまたは行列が実数値である限り、2つの演算子は同じ結果を生成します。しかし、 複雑な数値を扱うやいなや、「正しい」短縮形を使用しなければ、必然的に問題に遭遇します。 「正しい」とは、アプリケーションによって異なります。
複素数を含む行列C
次の例を考えてみましょう。
>> C = [1i, 2; 3*1i, 4]
C =
0.0000 + 1.0000i 2.0000 + 0.0000i
0.0000 + 3.0000i 4.0000 + 0.0000i
その短縮形を使って転置しましょう.'
(期間付き)。出力は期待どおりで、転置された形式のC
です。
>> C.'
ans =
0.0000 + 1.0000i 0.0000 + 3.0000i
2.0000 + 0.0000i 4.0000 + 0.0000i
さて、 '
(期間なしで) '
使いましょう。転位に加えて、複素値も複素共役に変換されていることがわかります。
>> C'
ans =
0.0000 - 1.0000i 0.0000 - 3.0000i
2.0000 + 0.0000i 4.0000 + 0.0000i
要約すると、エルミート共役を計算しようとするならば、複素共役は転置され、 '
(期間なしで) '
を使用します。値を複素共役化せずに転置を計算したいだけなら、 .'
(期間付き)。
Y型の入力引数の未定義関数またはメソッドX
これは、MATLABがあなたが呼び出そうとしている関数を見つけることができないと言っている、長年にわたる方法です。このエラーが発生する理由はいくつかあります。
この関数は、MATLABの現在のバージョンの後に導入されました
MATLABのオンラインドキュメントには、特定の関数がどのバージョンで導入されたかを判断するための非常に優れた機能があります。ドキュメントの各ページの左下にあります。
あなたの現在のバージョン( ver
)とこのバージョンを比較して、この機能があなたの特定のバージョンで利用可能かどうかを判断してください。そうでない場合は、 アーカイブされたバージョンのドキュメントを検索して、ご使用のバージョンに適した代替製品を見つけてください。
あなたはそのツールボックスを持っていません!
ベースのMATLABインストールには多数の関数があります。しかし、より特殊化された機能はツールボックス内にパッケージ化され、Mathworksによって個別に販売されます。ツールボックスがあるかどうかに関わらず、 すべてのツールボックスのドキュメントが表示されますので、適切なツールボックスがあるかどうかを確認して確認してください。
特定の機能が属するツールボックスを確認するには、オンラインドキュメントの左上を見て、特定のツールボックスが記載されているかどうかを確認します。
次に、インストールされているすべてのツールボックスのリストを出力するver
コマンドを発行することにより、ご使用のMATLABのバージョンがどのツールボックスであるかを判断できます。
そのツールボックスをインストールしておらず、その機能を使いたい場合は、The Mathworksからその特定のツールボックスのライセンスを購入する必要があります。
MATLABは関数を見つけることができません
MATLABがまだ関数を見つけることができない場合は、ユーザー定義関数でなければなりません。それは別のディレクトリに存在する可能性があり、実行するコードの検索パスにそのディレクトリを追加する必要があります。あなたは、MATLABが使用して機能を見つけることができるかどうかを確認することができwhich
ソースファイルへのパスを返すべきです。
浮動小数点の不正確さに注意してください
浮動小数点数はすべての実数を表すことはできません。これは、浮動小数点の不正確さとして知られています。
無限に多くの浮動小数点数があり、無限に長く(例えばπ
)することができるので、それらを完全に表現するには無限大のメモリが必要です。これを見ることは問題であり、 IEEE 754標準であるコンピュータの「実数」ストレージの特別な表現が設計されました。要約すると、コンピュータがこのタイプの数値をどのように格納するかを指数と仮数で、
floatnum = sign * 2^exponent * mantissa
これらのそれぞれのビット量が限られているため、有限の精度しか得られません。数字が小さいほど、可能な数字間のギャップが小さくなります(またその逆もあります)。 このオンラインデモであなたの実数を試すことができます。
この動作に注意して、すべての浮動小数点の比較とそのループ内の停止条件としての使用を避けてください。以下の2つの例を参照してください。
例:浮動小数点の比較を行ったWRONG:
>> 0.1 + 0.1 + 0.1 == 0.3
ans =
logical
0
前述の例に示すように、浮動小数点比較を使用することは貧弱な方法です。あなたは差の絶対値を取ってそれを(小さな)許容レベルと比較することによってそれを克服することができます。
以下は別の例です。ここでは浮動小数点数がwhileループの停止条件として使用されています:**
k = 0.1;
while k <= 0.3
disp(num2str(k));
k = k + 0.1;
end
% --- Output: ---
0.1
0.2
最後に予想されるループを逃している( 0.3 <= 0.3
)。
例:浮動小数点比較が完了した右:
x = 0.1 + 0.1 + 0.1;
y = 0.3;
tolerance = 1e-10; % A "good enough" tolerance for this case.
if ( abs( x - y ) <= tolerance )
disp('x == y');
else
disp('x ~= y');
end
% --- Output: ---
x == y
注意すべきいくつかの点:
- 予想どおり、
x
とy
は同等のものとして扱われます。 - 上記の例では、許容範囲の選択は任意に行われました。したがって、選択した値がすべての場合に適しているとは限りません(特に、はるかに小さい数値で作業する場合)。境界を知的に選択するには、
eps
関数、つまりN*eps(max(x,y))
。ここでN
は問題固有の数字です。許容できるN
の合理的な選択は、1E2
(ただし、上記の問題N=1
でも十分である)。
参考文献:
浮動小数点の不正確さの詳細については、次の質問を参照してください。
入力引数が十分ではありません
多くの場合、MATLABの開発者はMATLABのエディタを使用して、コードを記述し編集します。特に、入力と出力を持つカスタム関数があります。最上部には、最近のバージョンのMATLABで使用できる[ 実行 ]ボタンがあります。
開発者がコードを終了すると、 Runボタンを押すことがよくあります。いくつかの関数では正常に動作しますが、他の人にはNot enough input arguments
エラーが表示され、エラーが発生する理由について困惑します。
このエラーが発生しない理由は、入力引数を取らないMATLABスクリプトまたは関数を記述したためです。 実行ボタンを使用すると、テストスクリプトを実行するか、入力引数がないと仮定して関数を実行します。関数に入力引数が必要な場合、入力引数がNot enough input arguments
エラーは、入力が関数内に入ることを期待する関数を記述したときに発生します。したがって、 Runボタンを押すだけで、この機能が実行されることは期待できません。
この問題を示すには、単純に2つの行列を掛け合わせるmult
関数があるとします。
function C = mult(A, B)
C = A * B;
end
最近のバージョンのMATLABでは、この関数を記述して[ 実行 ]ボタンを押しても、期待していたエラーが表示されます:
>> mult
Not enough input arguments.
Error in mult (line 2)
C = A * B;
この問題を解決する方法は2つあります。
方法1 - コマンドプロンプトによる
コマンドプロンプトで必要な入力を作成し、作成した入力を使用して関数を実行します。
A = rand(5,5);
B = rand(5,5);
C = mult(A,B);
方法2 - エディタを介して対話的に
Runボタンの下に黒い黒い矢印があります。その矢印をクリックすると、方法1で見たのとまったく同じように関数を呼び出す方法を入力して、MATLABワークスペースから取得したい変数を指定できます。関数内で指定している変数がMATLABワークスペースに存在することを確認します。
配列サイズの変更に注意してください
MATLABの一般的な操作( 微分や積分など)では、入力データとは要素の量が異なる結果が出力されます。この事実は容易に見落とすことがMatrix dimensions must agree
ます。通常、 Matrix dimensions must agree
ようなエラーが発生します。次の例を考えてみましょう。
t = 0:0.1:10; % Declaring a time vector
y = sin(t); % Declaring a function
dy_dt = diff(y); % calculates dy/dt for y = sin(t)
これらの結果をプロットしたいとしましょう。配列のサイズを見てみましょう。
size(y) is 1x101
size(t) is 1x101
しかし:
size(dy_dt) is 1x100
配列は1つ短い要素です!
今度は、時間の経過に伴う位置の測定データがあり、 ジャーク(t)を計算したいと思うなら、ジャークが3回微分された位置であるため、時間配列より3つ少ない配列を取得します。
vel = diff(y); % calculates velocity vel=dy/dt for y = sin(t) size(vel)=1x100
acc = diff(vel); % calculates acceleration acc=d(vel)/dt size(acc)=1x99
jerk = diff(acc); % calculates jerk jerk=d(acc)/dt size(jerk)=1x98
そして、次のような操作:
x = jerk .* t; % multiplies jerk and t element wise
行列の次元が一致しないため、エラーを返します。
上記のような演算を計算するには、より小さな配列に合わせて大きな配列サイズを調整する必要があります。また、データに回帰( polyfit
)を実行して、データの多項式を得ることもできます。
ディメンションの不一致エラー
ディメンションの不一致エラーは、通常、次の場合に表示されます。
- 関数/メソッド呼び出しから返される変数の形には注意しないでください。多くの組み込みMATLAB関数では、行列がベクトルに変換されて計算が高速化され、返された変数は期待した行列ではなくベクトルになります。これは、 論理マスキングが関与する場合の一般的なシナリオです。
- 暗黙の配列展開を呼び出しながら、互換性のない配列サイズを使用する。
虚数単位、ループインデックスまたは共通変数としての "i"または "j"の使用。
勧告
シンボルi
とj
はMATLABではかなり異なるものを表すことができるため、ループインデックスとして使用すると、MATLABユーザコミュニティは年齢によって分割されます。歴史的なパフォーマンス上の理由によってバランスが片側に傾くのを助けるかもしれませんが、これはもはや事例ではなく、現在は選択肢が完全にあなたに任せられます。
Mathworksの現在の推奨事項は次のとおりです。
i
は関数なので、変数をオーバーライドして変数として使うことができます。ただし、複雑な算術演算で使用する場合は、変数名にi
とj
を使用しないでください。- 複素数演算の速度とロバスト性を向上させるには、
i
とj
代わりに1i
と1j
使用します。
デフォルト
MATLABでは、デフォルトで、文字i
とj
は組み込みfunction
名であり、両方とも複合ドメインの虚数単位を参照します。
ですから、デフォルトではi = j = sqrt(-1)
です。
>> i
ans =
0.0000 + 1.0000i
>> j
ans =
0.0000 + 1.0000i
期待通りに:
>> i^2
ans =
-1
それらを変数として使用する(ループインデックスやその他の変数のために)
MATLABでは、組み込みの関数名を標準変数として使用できます。この場合、使用されるシンボルは、組み込み関数を指し示すのではなく、あなた自身のユーザ定義変数を指します。ただし、混乱、困難なデバッグやメンテナンスにつながる可能性があるため、この方法は一般的には推奨されていません( 他の例では、関数名を持つ変数名を参照)。
あなたが規約やベストプラクティスを尊重することについて非常に賢明であれば、この言語でループインデックスとして使用することは避けてください。しかし、それはコンパイラによって許可され、完全に機能するので、古い習慣を保持してループイテレータとして使用することもできます。
>> A = nan(2,3);
>> for i=1:2 % perfectly legal loop construction
for j = 1:3
A(i, j) = 10 * i + j;
end
end
ループのインデックスは、ループの最後にスコープから外れないので、新しい値を保持します。
>> [ i ; j ]
ans =
2
3
変数として使用する場合は、それらが使用される前に初期化されていることを確認してください。上のループでは、MATLABはループを準備するときに自動的に初期化しますが、正しく初期化されないと誤って結果にcomplex
が導入されることがあります。
後で、組み込み関数のシャドーイングを元に戻す必要がある場合(= i
とj
虚数単位を再表示したい場合など)、変数をclear
することができます:
>> clear i j
複雑な算術演算でそれらを使用する予定の場合は、Mathworksの予約をループインデックスとして使用することについて、今すぐ理解しています。あなたのコードは、変数の初期化とclear
コマンド、最も深刻なプログラマー( はい、そこにいる!... )と起こるのを待っているプログラムの事故を混乱させる最良の方法ではぎとられます。
複雑な算術が必要ない場合、 i
とj
使用は完全に機能し、パフォーマンス上のペナルティはありません。
それらを虚数単位として使用する:
あなたのコードがcomplex
を扱わなければならないなら、 i
とj
は確かに便利でしょう。しかし、曖昧さ回避とパフォーマンスのためにも、簡略構文の代わりに完全形式を使用することをお勧めします。フルフォームは1i
(または1j
)です。
>> [ i ; j ; 1i ; 1j]
ans =
0.0000 + 1.0000i
0.0000 + 1.0000i
0.0000 + 1.0000i
0.0000 + 1.0000i
それらは同じ値sqrt(-1)
表しますが、後の形式:
- 意味的なやり方で、より明示的です。
- (あなたのコードを見ている人が、
i
またはj
が変数か虚数単位かどうかを調べるために、コードを後で読む必要はありません)。 - 高速です(出典:Mathworks)。
完全な構文1i
は、記号の前の任意の数字で有効です。
>> a = 3 + 7.8j
a =
3.0000 + 7.8000i
これは、それらの間に演算子を使用せずに番号をつけることができる唯一の機能です。
落とし穴
虚数単位 OR 変数としての使用は完全に合法ですが、ここでは、両方の用途が混在している場合にどのように混乱するかの小さな例です。
i
をオーバーライドして変数にしましょう:
>> i=3
i =
3
今i
は変数です (値3
保持しています)が、虚数単位の簡略表記だけを上書きしますが、完全な形式は正しく解釈されます。
>> 3i
ans =
0.0000 + 3.0000i
今では最もわかりにくい処方を作ることができます。以下のすべての構文の可読性を評価しましょう:
>> [ i ; 3i ; 3*i ; i+3i ; i+3*i ]
ans =
3.0000 + 0.0000i
0.0000 + 3.0000i
9.0000 + 0.0000i
3.0000 + 3.0000i
12.0000 + 0.0000i
ご覧のように、上記の配列の各値は異なる結果を返します。それぞれの結果は有効ですが(初期の意図であれば)、ほとんどの人は、そのような構成要素で包まれたコードを読むのは適切な悪夢であると認めます。
多次元配列に `length`を使う
MATLABコーダーによくある間違いは、( ベクトルとは対照的に)行列のlength
関数を使用していることです。 length
関数は、 そのドキュメントに記載されているように、入力の「 最大の配列次元の長さを返します。
ベクトルの場合、 length
の戻り値には2つの異なる意味があります。
- ベクトル内の要素の総数。
- ベクトルの最大の次元。
ベクトルとは異なり、2つ以上の非シングルトン(すなわちサイズが1
より大きい)次元の配列では、上記の値は等しくありません。これは、行列のlength
を使用することがあいまいである理由です。コードの意図を完全に明確にするために、ベクトルを使って作業しているときでも、次の関数の1つを使用することをお勧めします。
-
size(A)
-その要素の対応する次元に沿った要素の量含む行ベクトルを返しA
。 -
numel(A)
-の要素数を返しA
。prod(size(A))
相当します。 -
ndims(A)
- 配列A
次元数を返します。numel(size(A))
相当するnumel(size(A))
。
これは、入力が事前に分かっておらず、様々なサイズと形状を持つことができる、 "未来の証明"のベクトル化されたライブラリ関数を書くときに特に重要です。