#*******************************/ # 伝達関数のゲインと位相の計算 */ # coded by Y.Suganuma */ #*******************************/ #***************************/ # クラスComp */ # coded by Y.Suganuma */ #***************************/ class Comp # コンストラクタ def initialize(_real, _imag) @_real = _real @_imag = _imag end # 演算子のオーバーロード def +(obj) c = Comp.new(@_real+obj._real, @_imag+obj._imag) return c end def -(obj) c = Comp.new(@_real-obj._real, @_imag-obj._imag) return c end def *(obj) r = @_real * obj._real - @_imag * obj._imag i = @_imag * obj._real + @_real * obj._imag c = Comp.new(r, i) return c end def /(obj) x = 1.0 / (obj._real * obj._real + obj._imag * obj._imag) r = (@_real * obj._real + @_imag * obj._imag) * x i = (@_imag * obj._real - @_real * obj._imag) * x c = Comp.new(r, i) return c end # 複素数の絶対値 def c_abs() x = Math.sqrt(@_real * @_real + @_imag * @_imag) return x end # 複素数の角度 def angle() x = 0.0 if @_real != 0.0 || @_imag != 0.0 x = Math.atan2(@_imag, @_real) end return x end # 出力 def out(cr = "") printf "(%f, %f)%s", @_real, @_imag, cr end attr_accessor("_real", "_imag") end #**************/ # 複素数のn乗 #**************/ def pow(a, n) c = Comp.new(1, 0) if n >= 0 for i1 in 0 ... n c = c * a end else for i1 in 0 ... -n c = c * a end c1 = Comp.new(1, 0) c = c1 / c end return c end #*******************************************************************/ # 伝達関数のsにjωを代入した値の計算 */ # ff : ω(周波数) */ # ms : 分子の表現方法 */ # =0 : 多項式(si[0]+si[1]*s+si[1]*s^2+・・・) */ # =1 : 因数分解((si[0]+si[1]*s)*(si[2]+si[3]*s)*・・・) */ # m : 分子の次数 */ # si : 分子多項式の係数 */ # mb : 分母の表現方法 */ # =0 : 多項式(bo[0]+bo[1]*s+bo[1]*s^2+・・・) */ # =1 : 因数分解((bo[0]+bo[1]*s)*(bo[2]+bo[3]*s)*・・・) */ # n : 分母の次数 */ # bo : 分母多項式の係数 */ # return : 結果 */ #*******************************************************************/ def G_s(ff, ms, m, si, mb, n, bo) # 周波数を複素数に変換 f = Comp.new(0.0, ff) # 分子 x = value(f, ms, m, si) # 分母 y = value(f, mb, n, bo) return x / y end #***************************************************************/ # 多項式のsにjωを代入した値の計算 */ # f : jω(周波数,複素数) */ # ms : 多項式の表現方法 */ # =0 : 多項式(a[0]+a[1]*s+a[1]*s^2+・・・) */ # =1 : 因数分解((a[0]+a[1]*s)*(a[2]+a[3]*s)*・・・) */ # n : 多項式の次数 */ # a : 多項式の係数 */ # return : 結果 */ #***************************************************************/ def value(f, ms, n, a) u0 = Comp.new(0.0, 0.0) u1 = Comp.new(1.0, 0.0) # 因数分解されていない if ms == 0 x = u0 for i1 in 0 ... n+1 x = x + Comp.new(a[i1], 0.0) * pow(f, i1) end # 因数分解されている else if n == 0 x = Comp.new(a[0], 0.0) * u1 else x = u1 k1 = 2 * n i1 = 0 while i1 < k1 x = x * (Comp.new(a[i1], 0.0) + Comp.new(a[i1+1], 0.0) * f) i1 += 2 end end end return x end uc = 90.0 / Math.asin(1.0) # 単位変換用 # # データの入力 # # 出力ファイル名の入力とファイルのオープン s = gets().split(" ") o_fg = s[1] o_fp = s[3] og = open(o_fg, "w") op = open(o_fp, "w") # 伝達関数データ s = gets().split(" ") fl = Float(s[1]) fu = Float(s[2]) k = Integer(s[4]) # 分子 s = gets().split(" ") ms = Integer(s[1]) m = Integer(s[3]) # 因数分解されていない if ms == 0 k1 = m + 1 si = Array.new(k1) for i1 in 0 ... k1 si[i1] = Float(s[i1+5]) end # 因数分解されている else k1 = (m == 0) ? 1 : 2 * m si = Array.new(k1) for i1 in 0 ... k1 si[i1] = Float(s[i1+5]) end end # 分母 s = gets().split(" ") mb = Integer(s[1]) n = Integer(s[3]) # 因数分解されていない if mb == 0 k1 = n + 1 bo = Array.new(k1) for i1 in 0 ... k1 bo[i1] = Float(s[i1+5]) end # 因数分解されている else k1 = (n == 0) ? 1 : 2 * n bo = Array.new(k1) for i1 in 0 ... k1 bo[i1] = Float(s[i1+5]) end end # # ゲインと位相の計算 # phase = 0.0 h = (Math.log10(fu) - Math.log10(fl)) / k ff = Math.log10(fl) for i1 in 0 ... k+1 # 周波数の対数を元に戻す f = 10.0 ** ff # 値の計算 g = G_s(f, ms, m, si, mb, n, bo) # ゲインと位相の計算 gain = 20.0 * Math.log10(g.c_abs()) x = g.angle * uc while (phase-x).abs() > 180.0 if (x-phase > 180.0) x -= 360.0 else if (x-phase < -180.0) x += 360.0 end end end phase = x # 出力 og.printf("%f %f\n", f, gain) op.printf("%f %f\n", f, phase) # 次の周波数 ff += h end =begin ------------------------data1.txt---------------------------- ゲイン gain.txt 位相 phase.txt 周波数の下限と上限 0.01 100 分割数 100 分子の表現方法 0 次数 0 係数(次数が低い順) 1.0 分母の表現方法 0 次数 3 係数(次数が低い順) 1.0 11.1 11.1 1.0 ------------------------data2.txt---------------------------- ゲイン gain.txt 位相 phase.txt 周波数の下限と上限 0.01 100 分割数 100 分子の表現方法 1 次数 0 係数(次数が低い順) 1.0 分母の表現方法 1 次数 3 係数(次数が低い順) 1.0 0.1 1.0 1.0 1.0 10.0 =end
Ruby 内の Complex クラスを利用した場合
#*******************************/ # 伝達関数のゲインと位相の計算 */ # coded by Y.Suganuma */ #*******************************/ require 'complex' #*******************************************************************/ # 伝達関数のsにjωを代入した値の計算 */ # ff : ω(周波数) */ # ms : 分子の表現方法 */ # =0 : 多項式(si[0]+si[1]*s+si[1]*s^2+・・・) */ # =1 : 因数分解((si[0]+si[1]*s)*(si[2]+si[3]*s)*・・・) */ # m : 分子の次数 */ # si : 分子多項式の係数 */ # mb : 分母の表現方法 */ # =0 : 多項式(bo[0]+bo[1]*s+bo[1]*s^2+・・・) */ # =1 : 因数分解((bo[0]+bo[1]*s)*(bo[2]+bo[3]*s)*・・・) */ # n : 分母の次数 */ # bo : 分母多項式の係数 */ # return : 結果 */ #*******************************************************************/ def G_s(ff, ms, m, si, mb, n, bo) # 周波数を複素数に変換 f = Complex(0.0, ff) # 分子 x = value(f, ms, m, si) # 分母 y = value(f, mb, n, bo) return x / y end #***************************************************************/ # 多項式のsにjωを代入した値の計算 */ # f : jω(周波数,複素数) */ # ms : 多項式の表現方法 */ # =0 : 多項式(a[0]+a[1]*s+a[1]*s^2+・・・) */ # =1 : 因数分解((a[0]+a[1]*s)*(a[2]+a[3]*s)*・・・) */ # n : 多項式の次数 */ # a : 多項式の係数 */ # return : 結果 */ #***************************************************************/ def value(f, ms, n, a) u0 = Complex(0.0, 0.0) u1 = Complex(1.0, 0.0) # 因数分解されていない if ms == 0 x = u0 for i1 in 0 ... n+1 x = x + a[i1] * (f ** i1) end # 因数分解されている else if n == 0 x = a[0] * u1 else x = u1 k1 = 2 * n i1 = 0 while i1 < k1 x = x * (a[i1] + a[i1+1] * f) i1 += 2 end end end return x end uc = 90.0 / Math.asin(1.0) # 単位変換用 # # データの入力 # # 出力ファイル名の入力とファイルのオープン s = gets().split(" ") o_fg = s[1] o_fp = s[3] og = open(o_fg, "w") op = open(o_fp, "w") # 伝達関数データ s = gets().split(" ") fl = Float(s[1]) fu = Float(s[2]) k = Integer(s[4]) # 分子 s = gets().split(" ") ms = Integer(s[1]) m = Integer(s[3]) # 因数分解されていない if ms == 0 k1 = m + 1 si = Array.new(k1) for i1 in 0 ... k1 si[i1] = Float(s[i1+5]) end # 因数分解されている else k1 = (m == 0) ? 1 : 2 * m si = Array.new(k1) for i1 in 0 ... k1 si[i1] = Float(s[i1+5]) end end # 分母 s = gets().split(" ") mb = Integer(s[1]) n = Integer(s[3]) # 因数分解されていない if mb == 0 k1 = n + 1 bo = Array.new(k1) for i1 in 0 ... k1 bo[i1] = Float(s[i1+5]) end # 因数分解されている else k1 = (n == 0) ? 1 : 2 * n bo = Array.new(k1) for i1 in 0 ... k1 bo[i1] = Float(s[i1+5]) end end # # ゲインと位相の計算 # phase = 0.0 h = (Math.log10(fu) - Math.log10(fl)) / k ff = Math.log10(fl) for i1 in 0 ... k+1 # 周波数の対数を元に戻す f = 10.0 ** ff # 値の計算 g = G_s(f, ms, m, si, mb, n, bo) # ゲインと位相の計算 gain = 20.0 * Math.log10(g.abs()) x = g.arg * uc while (phase-x).abs() > 180.0 if (x-phase > 180.0) x -= 360.0 else if (x-phase < -180.0) x += 360.0 end end end phase = x # 出力 og.printf("%f %f\n", f, gain) op.printf("%f %f\n", f, phase) # 次の周波数 ff += h end =begin ------------------------data1.txt---------------------------- ゲイン gain.txt 位相 phase.txt 周波数の下限と上限 0.01 100 分割数 100 分子の表現方法 0 次数 0 係数(次数が低い順) 1.0 分母の表現方法 0 次数 3 係数(次数が低い順) 1.0 11.1 11.1 1.0 ------------------------data2.txt---------------------------- ゲイン gain.txt 位相 phase.txt 周波数の下限と上限 0.01 100 分割数 100 分子の表現方法 1 次数 0 係数(次数が低い順) 1.0 分母の表現方法 1 次数 3 係数(次数が低い順) 1.0 0.1 1.0 1.0 1.0 10.0 =end