2015-09-16 8 views
5

は、私は多くの場合、他の人のコードから来る行列と仕事をしなければならない、と行列の向きに関する明確な規則が常にありません(移調かどうか)と、特定の行/列が追加された場合。したがって、私は+.*-などのためMatlabのエラーメッセージにデバッグコードを追加しますか? MATLABで

Error using * 
Inner matrix dimensions must agree. 

と同様のエラー以下のエラーをデバッグする私の時間の大半を費やしています。

Iスイッチするかを知っている、と間違った寸法はに入ったところ、潜在的に推測するように、私は、次元を含めるには、このエラーメッセージを修正することができれば、それは私に多くの時間を節約できます。したがって、私は何とか手に寸法を含めるようにエラーメッセージを修正したいと思います:

Error using * 
Inner matrix dimensions must agree: 243 x 23 and 98 x 23. 

が、このことは可能ですし、もしそうなら、私はそれをどのように行うことができますか?私は現在、この情報をプリントアウトするデバッグコードの追加/削除/テストに多くの時間を費やしています。

+0

は、.mファイルを見つけることによって、(と思う)が可能ですそのコード内のエラー出力を検索し、両方の行列に 'size()'を含めます。 – Adriaan

+4

'dbstop if error'を使用すると、Matlabはエラーが発生した場所で正確に実行を停止します。変数ブラウザで可変サイズを確認し、改善されたコードを直接試すことができます。 – Daniel

+0

ありがとう、私は 'dbstop if error'について知りませんでした。非常に便利なコマンドです! – user1111929

答えて

5

のMatlabの各算術演算子を使用すると、その演算子を呼び出すときに呼び出されるassociated methodを持っています。例えば、*(行列乗算)に対応する方法はmtimesと呼ばれます。各オペレータに対して

、あなたがタイプdoubleの変数のための方法を定義することができます組み込みメソッドとその動作を変更すること:あなたのケースでは、組み込みのメソッドを呼び出し、次にチェックし、カスタムエラーが含まれます。このアプローチの

利点は以下のとおりです。

  • あなたのコード内のいかなる変更は neccessaryではありません:あなたは、通常**.+などを使用します。それらの(エラーチェック)動作は変更されます。 (と思う)デバッグが完了したら

  • は、あなただけのパスからカスタムメソッドを削除する必要があります。これにより、の正常な動作が復元され、スピード違反が回避されます。後で再度デバッグする必要がある場合は、修正されたメソッドをパスに戻すだけです。私は、例として*及びその関連mtimesを使用し、以下において

。あなたの新しいmtimesメソッドはMatlabのパスの適当なフォルダに置き、mtimesよりも優先させるべきです。つまり、フォルダはMatlabのpathにあるはずです。または、他のすべてより優先される現在のフォルダを使用することもできます。

選択したフォルダ内に@doubleという名前のフォルダを作成し、mtimes.mというファイルを作成します。これにより、*double入力で呼び出されたときに、mtimes.mファイルを使用する必要があることがMatlabに伝えられます。

mtimes.mの内容は、次の線に沿って何かすることwhould:

function C = mtimes(A,B) 
if ndims(A)~=2 || ndims(B)~=2 
    %// number of dimensions is incorrect 
    error('MATLAB:mtimes_modified:ndims', ... 
     'One of the arrays is not a matrix: numbers of dimensions are %i and %i',... 
     ndims(A), ndims(B)); 
elseif max(size(A))>1 & max(size(B))>1 size(A,2)~=size(B,1) 
    %// dimensions are not appropriate for matrix multiplication, 
    %// or for multiplying by a matrix by a scalar 
    error('MATLAB:plus_modified:dimagree',... 
     'Sizes do not match: %i x %i and %i x %i', ... 
     size(A,1), size(A,2), size(B,1), size(B,2)); 
else 
    C = builtin('mtimes', A, B); %// call actual mtimes to multiply matrices 
end 

例の結果:実際のエラーメッセージを修正

>> rand(3,4,5)*rand(6,7) 
Error using * (line 3) 
One of the arrays is not a matrix: numbers of dimensions are 3 and 2 

>> rand(3,4)*rand(2,5) 
Error using * (line 7) 
Sizes do not match: 3 x 4 and 2 x 5 

>> rand(3,4)*rand(4,2) 
ans = 
    0.3162 0.3009 
    1.2628 0.7552 
    1.2488 0.8559 
+0

は長いこと前のどこかでそれについて読んだことがありますが、私にとってあなたの答えは最初の具体例です。強くお勧めします!!! – scmg

+0

@scmgありがとう! –

7

あなたはtry-catch blockを使用することができます。

a = rand(12); 
b = rand(10); 

try 
    c = a*b; 
catch err 
    % Because err is read-only, generate new error structure 
    % We can copy most of old one 

    newerr.identifier = err.identifier; 
    newerr.cause = err.cause; 
    newerr.stack = err.stack; 
    newerr.message = sprintf('%s size(a): [%u, %u] size(b): [%u, %u]', err.message, size(a), size(b)); 
    error(newerr) % Throw new error 
end 

は今我々が得る:

Error using testcode (line 5) 
Inner matrix dimensions must agree. size(a): [12, 12] size(b): [10, 10] 
+0

しかし、行列を掛ける必要があるたびに、これをすべて行う必要がありますか?これを関数に配置する方が良いのではないでしょうか? –

+0

@ LuisMendoこれは単なる例ですが、ユーザーは好きなだけ実装することができます。 – excaza

2

あなたは行列の多くの計算でそれを行う必要がある場合は、あなたは、たとえば、このような関数を書くことができます。

function C = matproduct(A, B) 
try 
    C = A * B; 
catch ME 
    switch ME.identifier 
     case 'MATLAB:dimagree' 
      msg = [ME.message, ' Size of ', inputname(1), ' :', num2str(size(A)), '. Size of ', inputname(2), ' :', num2str(size(B)), '.']; 
     case 'MATLAB:innerdim' 
      msg = [ME.message, ' Size of ', inputname(1), ' :', num2str(size(A)), '. Size of ', inputname(2), ' :', num2str(size(B)), '.']; 
     % other cases and corresponding modified msg here 
    end 
    throw(MException(ME.identifier, msg)); 
end 
end 

ただし、速度に影響するかどうかはわかりません...たとえば、a * b * cの場合は、最初の入力の名前は表示できません。

関連する問題