2016年3月4日金曜日

MATLABで関数の積をplotする

MATLABで乗算を使うときは、* と .* の違いに充分注意しよう、特に 1変数関数を作るときに気をつけよう、という話。 

MATLABではforループを使わず、x軸として取り得る値を予め行列(ベクトル)化し、これを関数に与えてplotする、 というやり方をするわけですが、たとえば0以上1未満までをN点でplotしたい、なんてときは…

>> N=2^10; ts=1/N;
>> t=0:ts:1-ts;

(0から始まっているので、範囲の終わりで ts をひとつ引いておくとサンプル数や周期性の辻褄が合うよね、ってやつです。)

>> plot(sin(2*pi*10*t));

出来る。10Hzの正弦波を 0から1までplotしたものです。

>> plot(sin(2*pi*10*t)+sin(2*pi*20*t));

これも出来る。10Hzの正弦波と20Hzの正弦波を足しあわせた波形を0から1まで plot したものです。

じゃあ正弦波を掛け合わせた波形を plot するには? と思って + を * にすると…
>> plot(sin(2*pi*10*t)*sin(2*pi*20*t));
エラー:  * 
内部行列の次元は一致しなければなりません。

最初の2つ(特に加算)はうまく出来てるのに、何故*はうまくいかないんだろう……?
f(t) = sin(2*pi*10*t)*sin(2*pi*20*t);

実は、そもそも t が (1x1024) の行列なので、 初項の sin(2*pi*10*t) の結果が既に (1x1024) の行列になってるんです。 で、二項目の  sin(2*pi*20*t) もまた (1x1024) の行列になるものですから、 (1x1024)の行列 × (1x1024)の行列、を計算しようとしてエラーになるんですね。さすがMATLAB……

1変数関数をプロットするとき、すなわち y=f(t) を計算しようとしているときに想定している t はスカラー値なんですから、 行列が渡ってきたら行列の要素ごとに計算することにしておいたほうがいい、ということになります。

というわけで意図した通りになる書き方は、

f(t) = sin(2*pi*10.*t).*sin(2*pi*20.*t);

こうじゃよ、というお話でした。sin(2*pi*10*t)など単項の関数がそのままplot出来てしまえるだけに混乱しますね。


関数にパラメーターを与えるときも、そのパラメーターがスカラー値ならば同じような書き方をしておいたほうがいいようです。 例えばこんな感じ。もっと簡単な書き方はないものか…
function main

fs=2^10; ts=1/fs;
t=0:ts:1-ts;

plot(t,sinxsin(t, 2, 4));
hold on
plot(t,sin(2*pi*2.*t));
plot(t,sin(2*pi*4.*t));
hold off

end

function [ y ] = sinxsin( x, f1, f2 )
% sinxsin  return sin(2*pi*f1*x)*sin(2*pi*f1*x)
%   

y = sin(2*pi.*f1.*x).*sin(2*pi.*f2.*x);

end

0 件のコメント:

コメントを投稿