質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

Q&A

1回答

695閲覧

関数filterと自作のプログラムの不一致

kaeruuuun

総合スコア19

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

MacOS(OSX)

MacOSとは、Appleの開発していたGUI(グラフィカルユーザーインターフェース)を採用したオペレーションシステム(OS)です。Macintoshと共に、市場に出てGUIの普及に大きく貢献しました。

0グッド

0クリップ

投稿2021/08/09 01:54

編集2021/08/09 14:02

MATLABの関数にあるconvを使わないで以下の式を実現したくてプログラムを作成しているのですが出力結果がうまくいかず解決方法に悩んでいます。教えていただけないでしょうか。1つ前にも同様の質問をしていますが、プログラムを修正しています。
具体的にはフィルタ係数a,bを指定する際にa,bともに1より大きな値で指定するとfilter(b,a,x)でプロットした結果と一致するのですが、フィルタ係数を1より小さい値にしたときに一致しません。

matlab

1prompt = 'What is the value of "a" ? '; 2a = input(prompt); 3prompt = 'What is the value of "b" ? '; 4b = input(prompt); 5 6N=49; 7x = [1; zeros(N,1)]; 8 9 10 11b_length=length(b); 12a_length=length(a); 13k1=length(x)+length(b)-1; 14y1=zeros(1,N); 15y2=zeros(1,N); 16 17x1=length(x); 18y=zeros(1,N); 19 20 21 for n=1:k1 22 for k=max(1,n+1-x1):min(n,b_length) 23 24 y1(n)=y1(n)+x(n-k+1)*b(k); 25end 26 27 28%for m=1:a_length 29for m=max(1,n+1-x1):min(n,a_length) 30 y2(n)=y2(n)+y(n-m+1)*(-a(m)); 31 32 33end 34y(n)=y1(n)+y2(n); 35end 36plot(y) 37xlim([0 50]) 38

イメージ説明

左が自作のプログラムの結果で右がfilter関数を使った場合です。
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2021/08/16 04:38 編集

コードを詳しく読んでませんが、とりあえず気づいたことだけ書きます [その1] https://jp.mathworks.com/help/matlab/ref/filter.html#buagwwg-2 の「詳細」の「有理伝達関数」の、 「有理伝達関数は、次の差分方程式で表すこともできます。」 と書かれてるところのすぐ下の式を見てください 「a(1)」は左辺の係数であり、右辺で使われているのは「a(2)」以降です 質問に記載の式に合わせて「y(n)=...」とするには、右辺全体を「a(1)」で割ります a(1)を使うのはそこだけで、a(2)以降の使い方の個別のy()との掛け算には使いません a(1)の扱いが異なるので、質問者さんが書いたコードと filter(b,a,x) の結果は同じにはならないと思います for m=max(1,n+1-x1):min(n,a_length) を、a(1)を使わないように for m=max(2,n+2-x1):min(n,a_length) に変えて、 y(n)=y1(n)+y2(n); を y(n)=(y1(n)+y2(n))/a(1); に変えるのではないですかね [その2] 質問のコードを実行してもエラーになります y1, y2, yのサイズは y1=zeros(1,N); y2=zeros(1,N); y=zeros(1,N); なので、どれもN=49です k1は k1=length(x)+length(b)-1; なので、length(x)=50以上ですから、 for n=1:k1 でnは50以上になり、そのループ内での y1(n)=... y2(n)=... y(n)=... で、サイズが49しかないy1, y2, yに、それよりも大きなnでアクセスしようとして、エラーになります y1, y2, yのサイズを、 y1=zeros(1,x1); y2=zeros(1,x1); y=zeros(1,x1); でxと同じx1にして、 for n=1:k1 を for n=1:x1 に変えるのではないですかね
guest

回答1

0

filter
の「詳細」の「有理伝達関数」の、
「有理伝達関数は、次の差分方程式で表すこともできます。」
と書かれてるところのすぐ下の式を見てください
「a(1)」は左辺の係数であり、右辺で使われているのは「a(2)」以降です

質問に記載の式に合わせて「y(n)=...」とするには、右辺全体を「a(1)」で割ります
a(1)を使うのはそこだけで、a(2)以降の使い方の個別のy()との掛け算には使いません

a(1)の扱いが異なるので、質問者さんが書いたコードと
filter(b, a, x)
の結果は同じにはならないと思いますので、そこを直しました

matlab

1N=49; 2x = [1; zeros(N,1)]; 3 4abl = randi(N); 5a = rand(1, abl); 6b = rand(1, abl); 7 8b_length=length(b); 9a_length=length(a); 10x1=length(x); 11y1=zeros(1,x1); 12y2=zeros(1,x1); 13y=zeros(1,x1); 14 15for n=1:x1 16 for k=max(1,n+1-x1):min(n,b_length) 17 y1(n)=y1(n)+x(n-k+1)*b(k); 18 end 19 20 for m=max(2,n+2-x1):min(n,a_length) 21 y2(n)=y2(n)+y(n-m+1)*(-a(m)); 22 end 23 24 y(n)=(y1(n)+y2(n))/a(1); 25end 26 27g = filter(b, a, x); 28 29plot(1:x1, y, 1:x1, g) 30 31err = (y - g') ./ g'; 32disp(max(err)) 33disp(min(err))

a, bを乱数で決めているので実行する度に結果が変わりますが、常にグラフがピッタリ重なります
また、相対誤差を数値で表示してますが、とても小さな値(数値計算誤差)にしかなりません

比較のため、質問に記載のコードから、同様にa, bを乱数で決めるように変えたものを、以下に掲載します
実行してみると、ほとんどの場合でグラフが重なりません

matlab

1N=49; 2x = [1; zeros(N,1)]; 3 4abl = randi(N) 5a = rand(1, abl) 6b = rand(1, abl) 7 8b_length=length(b); 9a_length=length(a); 10k1=length(x)+length(b)-1; 11y1=zeros(1,N); 12y2=zeros(1,N); 13x1=length(x); 14y=zeros(1,N); 15 16for n=1:k1 17 for k=max(1,n+1-x1):min(n,b_length) 18 y1(n)=y1(n)+x(n-k+1)*b(k); 19 end 20 21 for m=max(1,n+1-x1):min(n,a_length) 22 y2(n)=y2(n)+y(n-m+1)*(-a(m)); 23 end 24 25 y(n)=y1(n)+y2(n); 26end 27 28g = filter(b, a, x); 29 30plot(1:N, y, 1:x1, g)

投稿2021/08/23 10:46

jbpb0

総合スコア7653

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問