------------------------data1----------------------------
ゲイン gain 位相 phase
周波数の下限と上限 0.01 100 分割数 100
分子の表現方法 0 次数 0 係数(次数が低い順) 1.0
分母の表現方法 0 次数 3 係数(次数が低い順) 1.0 11.1 11.1 1.0
------------------------data2----------------------------
ゲイン gain 位相 phase
周波数の下限と上限 0.01 100 分割数 100
分子の表現方法 1 次数 0 係数(次数が低い順) 1.0
分母の表現方法 1 次数 3 係数(次数が低い順) 1.0 0.1 1.0 1.0 1.0 10.0
------------------------complex.h------------------------
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
#include <iostream>
#include <math.h>
using namespace std;
class Complex {
double r; // 実部
double i; // 虚部
public:
Complex (double a = 0.0, double b = 0.0); // コンストラクタ
friend double abs (Complex a); // 絶対値
friend double angle (Complex a); // 角度
friend Complex pow (Complex a, int n); // べき乗
friend Complex operator +(Complex a, Complex b); // +のオーバーロード
friend Complex operator -(Complex a, Complex b); // ーのオーバーロード
friend Complex operator *(Complex a, Complex b); // *のオーバーロード
friend Complex operator /(Complex a, Complex b); // /のオーバーロード
friend ostream& operator << (ostream&, Complex); // <<のオーバーロード
};
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
Complex::Complex(double a, double b)
{
r = a;
i = b;
}
/******************/
/* 複素数の絶対値 */
/******************/
double abs(Complex a)
{
double x;
x = sqrt(a.r * a.r + a.i * a.i);
return x;
}
/****************/
/* 複素数の角度 */
/****************/
double angle(Complex a)
{
double x;
if (a.r == 0.0 && a.i == 0.0)
x = 0.0;
else
x = atan2(a.i, a.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
Complex pow(Complex a, int n)
{
int i1;
Complex c(1, 0);
if (n >= 0) {
for (i1 = 0; i1 < n; i1++)
c = c * a;
}
else {
for (i1 = 0; i1 < -n; i1++)
c = c * a;
c = 1.0 / c;
}
return c;
}
/**********************/
/* +のオーバーロード */
/**********************/
Complex operator +(Complex a, Complex b)
{
Complex c;
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
/**********************/
/* ーのオーバーロード */
/**********************/
Complex operator -(Complex a, Complex b)
{
Complex c;
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
/**********************/
/* *のオーバーロード */
/**********************/
Complex operator *(Complex a, Complex b)
{
Complex c;
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
/**********************/
/* /のオーバーロード */
/**********************/
Complex operator /(Complex a, Complex b)
{
double x;
Complex c;
x = 1.0 / (b.r * b.r + b.i * b.i);
c.r = (a.r * b.r + a.i * b.i) * x;
c.i = (a.i * b.r - a.r * b.i) * x;
return c;
}
/************************/
/* <<のオーバーロード */
/************************/
ostream& operator << (ostream& stream, Complex a)
{
stream << "(" << a.r << ", " << a.i << ")";
return stream;
}
------------------------main-----------------------------
/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
#include <stdio.h>
#include <stdlib.h>
#include "complex.h"
Complex G_s(double, int, int, double *, int, int, double *);
Complex value(Complex, int, int, double *);
int main()
{
double f, ff, fl, fu, h, *bo, *si, gain, phase = 0.0, x, uc;
int i1, k, k1, ms, mb, m, n;
char o_fg[100], o_fp[100];
Complex g;
FILE *og, *op;
uc = 90.0 / asin(1.0);
/*
データの入力
*/
// 出力ファイル名の入力とファイルのオープン
scanf("%*s %s %*s %s", o_fg, o_fp);
og = fopen(o_fg, "w");
op = fopen(o_fp, "w");
// 伝達関数データ
scanf("%*s %lf %lf %*s %d", &fl, &fu, &k);
// 分子
scanf("%*s %d %*s %d %*s", &ms, &m);
// 因数分解されていない
if (ms == 0) {
k1 = m + 1;
si = new double [k1];
for (i1 = 0; i1 < k1; i1++)
scanf("%lf", &si[i1]);
}
// 因数分解されている
else {
k1 = (m == 0) ? 1 : 2 * m;
si = new double [k1];
for (i1 = 0; i1 < k1; i1++)
scanf("%lf", &si[i1]);
}
// 分母
scanf("%*s %d %*s %d %*s", &mb, &n);
// 因数分解されていない
if (mb == 0) {
k1 = n + 1;
bo = new double [k1];
for (i1 = 0; i1 < k1; i1++)
scanf("%lf", &bo[i1]);
}
// 因数分解されている
else {
k1 = (n == 0) ? 1 : 2 * n;
bo = new double [k1];
for (i1 = 0; i1 < k1; i1++)
scanf("%lf", &bo[i1]);
}
/*
ゲインと位相の計算
*/
h = (log10(fu) - log10(fl)) / k;
ff = log10(fl);
for (i1 = 0; i1 <= k; i1++) {
// 周波数の対数を元に戻す
f = pow(10.0, ff);
// 値の計算
g = G_s(f, ms, m, si, mb, n, bo);
// ゲインと位相の計算
gain = 20.0 * log10(abs(g));
x = angle(g) * uc;
while (fabs(phase-x) > 180.0) {
if (x-phase > 180.0)
x -= 360.0;
else {
if (x-phase < -180.0)
x += 360.0;
}
}
phase = x;
// 出力
fprintf(og, "%f %f\n", f, gain);
fprintf(op, "%f %f\n", f, phase);
// 次の周波数
ff += h;
}
return 0;
}
/********************************************************************/
/* 伝達関数の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 : 結果 */
/********************************************************************/
Complex G_s(double ff, int ms, int m, double *si, int mb, int n, double *bo)
{
Complex f, x, y;
// 周波数を複素数に変換
f = Complex (0.0, ff);
// 分子
x = value(f, ms, m, si);
// 分母
y = value(f, mb, n, bo);
return x / y;
}
/****************************************************************/
/* 多項式の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 : 結果 */
/****************************************************************/
Complex value(Complex f, int ms, int n, double *a)
{
int i1, k1;
Complex u0(0.0, 0.0), u1(1.0, 0.0), x;
// 因数分解されていない
if (ms == 0) {
x = u0;
for (i1 = 0; i1 <= n; i1++)
x = x + a[i1] * pow(f, i1);
}
// 因数分解されている
else {
if (n == 0)
x = a[0] * u1;
else {
x = u1;
k1 = 2 * n;
for (i1 = 0; i1 < k1; i1 += 2)
x = x * (a[i1] + a[i1+1] * f);
}
}
return x;
}