| 情報学部 | 菅沼ホーム | 目次 | 索引 |
周波数1 ゲイン1(または,位相1) 周波数2 ゲイン2(または,位相2) ・・・・・・・
/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
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;
}
Complex G_s(double, int, int, double *, int, int, double *);
Complex value(Complex, int, int, double *);
/*******************/
/* main プログラム */
/*******************/
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;
}
/*
------------------------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
*/
/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
import java.io.*;
import java.util.StringTokenizer;
public class Test {
/****************/
/* main program */
/****************/
public static void main(String args[]) throws IOException
{
double f, ff, fl, fu, h, gain, phase = 0.0, x, uc;
double bo[] = new double [1];
double si[] = new double [1];
int i1, k, k1, ms, mb, m, n;
Complex g;
String str;
StringTokenizer token;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
uc = 90.0 / Math.asin(1.0);
/*
データの入力
*/
// 出力ファイル名とファイルのオープン
str = in.readLine();
token = new StringTokenizer(str, " ");
token.nextToken();
PrintStream g_o = new PrintStream(new FileOutputStream(token.nextToken()));
token.nextToken();
PrintStream p_o = new PrintStream(new FileOutputStream(token.nextToken()));
// 伝達関数データ
str = in.readLine();
token = new StringTokenizer(str, " ");
token.nextToken();
fl = Double.parseDouble(token.nextToken());
fu = Double.parseDouble(token.nextToken());
token.nextToken();
k = Integer.parseInt(token.nextToken());
// 分子
str = in.readLine();
token = new StringTokenizer(str, " ");
token.nextToken();
ms = Integer.parseInt(token.nextToken());
token.nextToken();
m = Integer.parseInt(token.nextToken());
token.nextToken();
// 因数分解されていない
if (ms == 0) {
k1 = m + 1;
si = new double [k1];
for (i1 = 0; i1 < k1; i1++)
si[i1] = Double.parseDouble(token.nextToken());
}
// 因数分解されている
else {
k1 = (m == 0) ? 1 : 2 * m;
si = new double [k1];
for (i1 = 0; i1 < k1; i1++)
si[i1] = Double.parseDouble(token.nextToken());
}
// 分母
str = in.readLine();
token = new StringTokenizer(str, " ");
token.nextToken();
mb = Integer.parseInt(token.nextToken());
token.nextToken();
n = Integer.parseInt(token.nextToken());
token.nextToken();
// 因数分解されていない
if (mb == 0) {
k1 = n + 1;
bo = new double [k1];
for (i1 = 0; i1 < k1; i1++)
bo[i1] = Double.parseDouble(token.nextToken());
}
// 因数分解されている
else {
k1 = (n == 0) ? 1 : 2 * n;
bo = new double [k1];
for (i1 = 0; i1 < k1; i1++)
bo[i1] = Double.parseDouble(token.nextToken());
}
/*
ゲインと位相の計算
*/
h = (log10(fu) - log10(fl)) / k;
ff = log10(fl);
for (i1 = 0; i1 <= k; i1++) {
// 周波数の対数を元に戻す
f = Math.pow(10.0, ff);
// 値の計算
g = G_s(f, ms, m, si, mb, n, bo);
// ゲインと位相の計算
gain = 20.0 * log10(Complex.abs(g));
x = Complex.angle(g) * uc;
while (Math.abs(phase-x) > 180.0) {
if (x-phase > 180.0)
x -= 360.0;
else {
if (x-phase < -180.0)
x += 360.0;
}
}
phase = x;
// 出力
g_o.println(f + " " + gain);
p_o.println(f + " " + phase);
// 次の周波数
ff += h;
}
g_o.close();
p_o.close();
}
/************/
/* log10(x) */
/************/
static double log10(double x)
{
return Math.log(x) / Math.log(10.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 : 結果 */
/********************************************************************/
static Complex G_s(double ff, int ms, int m, double si[], int mb, int n, double bo[])
{
Complex f, x, y;
// 周波数を複素数に変換
f = new Complex (0.0, ff);
// 分子
x = value(f, ms, m, si);
// 分母
y = value(f, mb, n, bo);
return Complex.dev(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 : 結果 */
/****************************************************************/
static Complex value(Complex f, int ms, int n, double a[])
{
int i1, k1;
Complex x;
// 因数分解されていない
if (ms == 0) {
x = new Complex (0.0, 0.0);
for (i1 = 0; i1 <= n; i1++)
x = Complex.add(x, Complex.mul(new Complex(a[i1]), Complex.pow(f, i1)));
}
// 因数分解されている
else {
if (n == 0)
x = new Complex (a[0]);
else {
x = new Complex (1.0, 0.0);
k1 = 2 * n;
for (i1 = 0; i1 < k1; i1 += 2)
x = Complex.mul(x, Complex.add(new Complex(a[i1]), Complex.mul(new Complex(a[i1+1]), f)));
}
}
return x;
}
}
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
class Complex {
private double r; // 実部
private double i; // 虚部
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
Complex(double a, double b)
{
r = a;
i = b;
}
/******************/
/* コンストラクタ */
/* a : 実部 */
/******************/
Complex(double a)
{
r = a;
i = 0.0;
}
/******************/
/* コンストラクタ */
/******************/
Complex()
{
r = 0.0;
i = 0.0;
}
/********/
/* 出力 */
/********/
void output(PrintStream out, Complex a)
{
out.print("(" + a.r + ", " + a.i + ")");
}
/******************/
/* 複素数の絶対値 */
/******************/
static double abs(Complex a)
{
double x;
x = Math.sqrt(a.r * a.r + a.i * a.i);
return x;
}
/****************/
/* 複素数の角度 */
/****************/
static double angle(Complex a)
{
double x;
if (a.r == 0.0 && a.i == 0.0)
x = 0.0;
else
x = Math.atan2(a.i, a.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
static Complex pow(Complex a, int n)
{
int i1;
Complex c = new Complex (1);
if (n >= 0) {
for (i1 = 0; i1 < n; i1++)
c = Complex.mul(c, a);
}
else {
for (i1 = 0; i1 < -n; i1++)
c = Complex.mul(c, a);
c = Complex.dev(new Complex(1.0), c);
}
return c;
}
/****************/
/* 複素数の加算 */
/****************/
static Complex add(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
/****************/
/* 複素数の減算 */
/****************/
static Complex sub(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
/****************/
/* 複素数の乗算 */
/****************/
static Complex mul(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
/****************/
/* 複素数の除算 */
/****************/
static Complex dev(Complex a, Complex b)
{
double x;
Complex c = new Complex();
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;
}
}
/*
------------------------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
*/
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>ボード線図</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<SCRIPT TYPE="text/javascript">
max_g = 5;
max_order = 10;
n_g = 1;
function main()
{
// 入力データの有無チェック
n_g = parseInt(document.getElementById("n_g").value);
let err = 0;
for (let i1 = 0; i1 < n_g; i1++) {
let str1 = "s" + i1;
let str2 = document.getElementById(str1).value;
if (str2 == "") {
err = 1;
alert((i1+1) + " 番目の式の分子の次数を入力して下さい");
}
else {
let k1 = parseInt(str2);
for (let i2 = 0; i2 <= k1; i2++) {
str1 = "s" + i1 + i2;
str2 = document.getElementById(str1).value;
if (str2 == "") {
err = 1;
alert((i1+1) + " 番目の式の分子の" + i2 + "次の項を入力して下さい");
}
}
}
str1 = "b" + i1;
str2 = document.getElementById(str1).value;
if (str2 == "") {
err = 1;
alert((i1+1) + " 番目の式の分母の次数を入力して下さい");
}
else {
let k1 = parseInt(str2);
for (let i2 = 0; i2 <= k1; i2++) {
str1 = "b" + i1 + i2;
str2 = document.getElementById(str1).value;
if (str2 == "") {
err = 1;
alert((i1+1) + " 番目の式の分子の" + i2 + "次の項を入力して下さい");
}
}
}
}
if (err == 0) {
// ゲインと位相の計算
let fl = parseFloat(document.getElementById("low").value);
let fu = parseFloat(document.getElementById("up").value);
let k = parseInt(document.getElementById("n_data").value);
// 下限と上限の再設定
if (fl < 1.0) {
let x = 0.1;
while (fl < x-1.0e-10)
x /= 10.0;
fl = x;
}
else {
let x = 1.0;
while (fl > x-1.0e-10)
x *= 10.0;
fl = x;
}
if (fu < 1.0) {
let x = 0.1;
while (fu < x+1.0e-10)
x /= 10.0;
fu = 10.0 * x;
}
else {
let x = 1.0;
while (fu > x+1.0e-10)
x *= 10.0;
fu = x;
}
// 初期設定
let uc = 90.0 / Math.asin(1.0);
let g_title = new Array(); // グラフタイトル
let m = new Array(); // 分子の次数
let n = new Array(); // 分母の次数
let si = new Array(); // 分子の係数
let bo = new Array(); // 分母の係数
let freq1 = new Array(); // ゲイン線図の周波数
let freq2 = new Array(); // 位相線図の周波数
let gain = new Array(); // ゲイン
let phase = new Array(); // 位相
for (let i1 = 0; i1 < n_g; i1++) {
si[i1] = new Array();
bo[i1] = new Array();
freq1[i1] = new Array();
freq2[i1] = new Array();
gain[i1] = new Array();
phase[i1] = new Array();
}
let h = (log10(fu) - log10(fl)) / k;
let g_min = 0.0;
let g_max = 0.0;
let p_min = 0.0;
let p_max = 0.0;
let ta = " 角周波数 ゲイン(dB) 位相(度)\n";
for (let i1 = 0; i1 < n_g; i1++) {
// データの取得
g_title[i1] = document.getElementById("exp"+i1).value;
let str = "s" + i1;
m[i1] = parseInt(document.getElementById(str).value);
for (let i2 = 0; i2 <= m[i1]; i2++) {
str = "s" + i1 + i2;
si[i1][i2] = parseFloat(document.getElementById(str).value);
}
str = "b" + i1;
n[i1] = parseInt(document.getElementById(str).value);
for (let i2 = 0; i2 <= n[i1]; i2++) {
str = "b" + i1 + i2;
bo[i1][i2] = parseFloat(document.getElementById(str).value);
}
// 計算
ff = log10(fl);
ta = ta + g_title[i1] + "\n";
for (let i2 = 0; i2 <= k; i2++) {
// 周波数の対数を元に戻す
let f = Math.pow(10.0, ff);
freq1[i1][i2] = Math.round(100 * f) / 100;
freq2[i1][i2] = Math.round(100 * f) / 100;
ta = ta + " " + f;
// 値の計算
let g = G_s(f, m[i1], si[i1], n[i1], bo[i1]);
// ゲインの計算
gain[i1][i2] = 20.0 * log10(g.abs());
ta = ta + " " + gain[i1][i2];
if (i1 == 0 && i2 == 0) {
g_min = gain[i1][i2];
g_max = gain[i1][i2];
}
else {
if (gain[i1][i2] > g_max)
g_max = gain[i1][i2];
else if (gain[i1][i2] < g_min)
g_min = gain[i1][i2];
}
gain[i1][i2] = Math.round(100 * gain[i1][i2]) / 100;
// 位相の計算
let x = g.angle() * uc;
if (i2 > 0) {
while (Math.abs(phase[i1][i2-1]-x) > 180.0) {
if (x-phase[i1][i2-1] > 180.0)
x -= 360.0;
else {
if (x-phase[i1][i2-1] < -180.0)
x += 360.0;
}
}
}
phase[i1][i2] = Math.round(10 * x) / 10;
ta = ta + " " + x + "\n";
if (i1 == 0 && i2 == 0) {
p_min = phase[i1][i2];
p_max = phase[i1][i2];
}
else {
if (phase[i1][i2] > p_max)
p_max = phase[i1][i2];
else if (phase[i1][i2] < p_min)
p_min = phase[i1][i2];
}
// 次の周波数
ff += h;
}
}
document.getElementById("ans").value = ta;
// グラフの描画
// ゲイン線図
// タイトル
let gp1 = "7,ゲイン線図,角周波数,ゲイン(dB)," + n_g;
for (let i1 = 0; i1 < n_g; i1++)
gp1 = gp1 + "," + g_title[i1];
// x軸目盛り
gp1 = gp1 + "," + fl + "," + fu + ",1.0";
let p = 0;
if (fl < 1.0) {
p = 1;
x = 0.1;
while (fl < x-1.0e-10) {
x /= 10.0;
p++;
}
}
gp1 = gp1 + "," + p;
// y軸目盛り
if ((g_max-g_min) < 1.0e-5) {
if (g_min > 0.0) {
let k1 = Math.round(g_min / 20);
gp1 = gp1 + "," + (20.0 * k1 - 20.0);
gp1 = gp1 + "," + (20.0 * k1 + 20.0);
}
else {
let k1 = Math.round(-g_min / 20);
gp1 = gp1 + "," + (-20.0 * k1 - 20.0);
gp1 = gp1 + "," + (-20.0 * k1 + 20.0);
}
}
else {
if (g_min > 0.0) {
let k1 = Math.floor(g_min / 20);
gp1 = gp1 + "," + (20.0 * k1);
}
else {
let k1 = Math.floor(-g_min / 20);
if (Math.abs(-20.0*k1-g_min) > 1.0e-5)
k1++;
gp1 = gp1 + "," + (-20.0 * k1);
}
if (g_max > 0.0) {
let k1 = Math.floor(g_max / 20);
if (Math.abs(20.0*k1-g_max) > 1.0e-5)
k1++;
gp1 = gp1 + "," + (20.0 * k1);
}
else {
let k1 = Math.floor(-g_max / 20);
gp1 = gp1 + "," + (-20.0 * k1);
}
}
gp1 = gp1 + ",20.0,0";
// データ
gp1 = gp1 + "," + (k + 1);
for (let i1 = 0; i1 < n_g; i1++) {
for (let i2 = 0; i2 <= k; i2++)
gp1 = gp1 + "," + freq1[i1][i2];
for (let i2 = 0; i2 <= k; i2++)
gp1 = gp1 + "," + gain[i1][i2];
}
// 表示
gp1 = gp1 + ",1";
if (n_g == 1)
gp1 = gp1 + ",0";
else
gp1 = gp1 + ",1";
let str = "graph_js.htm?gp=" + gp1;
open(str, "gain", "width=950, height=700");
// 位相線図
// タイトル
let gp2 = "7,位相線図,角周波数,位相(度)," + n_g;
for (let i1 = 0; i1 < n_g; i1++)
gp2 = gp2 + "," + g_title[i1];
// x軸目盛り
gp2 = gp2 + "," + fl + "," + fu + ",1.0," + p;
// y軸目盛り
if ((p_max-p_min) < 1.0e-5) {
if (p_min > 0.0) {
let k1 = Math.round(p_min / 90);
gp2 = gp2 + "," + (90.0 * k1 - 90.0);
gp2 = gp2 + "," + (90.0 * k1 + 90.0);
}
else {
let k1 = Math.round(-p_min / 90);
gp2 = gp2 + "," + (-90.0 * k1 - 90.0);
gp2 = gp2 + "," + (-90.0 * k1 + 90.0);
}
}
else {
if (p_min > 0.0) {
let k1 = Math.floor(p_min / 90);
gp2 = gp2 + "," + (90.0 * k1);
}
else {
let k1 = Math.floor(-p_min / 90);
if (Math.abs(-90.0*k1-p_min) > 1.0e-5)
k1++;
gp2 = gp2 + "," + (-90.0 * k1);
}
if (p_max > 0.0) {
let k1 = Math.floor(p_max / 90);
if (Math.abs(90.0*k1-p_max) > 1.0e-5)
k1++;
gp2 = gp2 + "," + (90.0 * k1);
}
else {
let k1 = Math.floor(-p_max / 90);
gp2 = gp2 + "," + (-90.0 * k1);
}
}
gp2 = gp2 + ",90.0,0";
// データ
gp2 = gp2 + "," + (k + 1);
for (let i1 = 0; i1 < n_g; i1++) {
for (let i2 = 0; i2 <= k; i2++)
gp2 = gp2 + "," + freq2[i1][i2];
for (let i2 = 0; i2 <= k; i2++)
gp2 = gp2 + "," + phase[i1][i2];
}
// 表示
gp2 = gp2 + ",1";
if (n_g == 1)
gp2 = gp2 + ",0";
else
gp2 = gp2 + ",1";
str = "graph_js.htm?gp=" + gp2;
open(str, "phase", "width=950, height=700");
}
}
/************/
/* log10(x) */
/************/
function log10(x)
{
return Math.log(x) / Math.log(10.0);
}
/****************************************/
/* 伝達関数のsにjωを代入した値の計算 */
/* ff : ω(周波数) */
/* m : 分子の次数 */
/* si : 分子多項式の係数 */
/* n : 分母の次数 */
/* bo : 分母多項式の係数 */
/* return : 結果 */
/****************************************/
function G_s(ff, m, si, n, bo)
{
let f;
let x;
let y;
// 周波数を複素数に変換
f = new Complex (0.0, ff);
// 分子
x = value(f, m, si);
// 分母
y = value(f, n, bo);
return x.dev(y);
}
/**************************************/
/* 多項式のsにjωを代入した値の計算 */
/* f : jω(周波数,複素数) */
/* n : 多項式の次数 */
/* a : 多項式の係数 */
/* return : 結果 */
/**************************************/
function value(f, n, a)
{
let i1;
let k1;
let z = new Complex (0.0, 0.0);
for (i1 = 0; i1 <= n; i1++) {
let x = new Complex(a[i1], 0.0);
let y = f.pow(i1);
x = x.mul(y);
z = z.add(x);
}
return z;
}
/************************/
/* Complex オブジェクト */
/************************/
function Complex(rr, ii)
{
this.r = rr; // 実部
this.i = ii; // 虚部
}
/******************/
/* 複素数の絶対値 */
/******************/
Complex.prototype.abs = function()
{
return Math.sqrt(this.r * this.r + this.i * this.i);
}
/****************/
/* 複素数の角度 */
/****************/
Complex.prototype.angle = function()
{
let x;
if (this.r == 0.0 && this.i == 0.0)
x = 0.0;
else
x = Math.atan2(this.i, this.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
Complex.prototype.pow = function(n)
{
let i1;
let c = new Complex(1.0, 0.0);
if (n >= 0) {
for (i1 = 0; i1 < n; i1++)
c = c.mul(this);
}
else {
for (i1 = 0; i1 < -n; i1++)
c = c.mul(this);
b = new Complex(1.0, 0.0);
c = b.dev(c);
}
return c;
}
/****************/
/* 複素数の加算 */
/****************/
Complex.prototype.add = function(b)
{
let c = new Complex(0.0, 0.0);
c.r = this.r + b.r;
c.i = this.i + b.i;
return c;
}
/****************/
/* 複素数の減算 */
/****************/
Complex.prototype.sub = function(b)
{
let c = new Complex(0.0, 0.0);
c.r = this.r - b.r;
c.i = this.i - b.i;
return c;
}
/****************/
/* 複素数の乗算 */
/****************/
Complex.prototype.mul = function(b)
{
let c = new Complex(0.0, 0.0);
c.r = this.r * b.r - this.i * b.i;
c.i = this.i * b.r + this.r * b.i;
return c;
}
/****************/
/* 複素数の除算 */
/****************/
Complex.prototype.dev = function(b)
{
let c = new Complex(0.0, 0.0);
let x = 1.0 / (b.r * b.r + b.i * b.i);
c.r = (this.r * b.r + this.i * b.i) * x;
c.i = (this.i * b.r - this.r * b.i) * x;
return c;
}
/*****************************************/
/* 式の数や次数の変更 */
/* kind = -1 : 式の数の変更 */
/* >= : 次数の変更(式番号-1) */
/* sw = 1 : 分子 */
/* 2 : 分母 */
/*****************************************/
function change(kind, sw)
{
// 式の数
if (kind < 0) {
let str = document.getElementById("n_g").value;
// 初期状態
if (str == "") {
for (let i1 = 0; i1 < max_g; i1++) {
str = "div" + i1;
document.getElementById(str).style.display = "none";
}
}
// 式の数が入力されたとき
else {
n_g = parseInt(str);
for (let i1 = 0; i1 < n_g; i1++) {
str = "div" + i1;
document.getElementById(str).style.display = "";
str = "s" + i1;
if (document.getElementById(str).value == "") {
for (let i2 = 0; i2 <= max_order; i2++) {
str = "s" + i1 + i2 + "_t";
document.getElementById(str).style.display = "none";
}
}
else {
let n = parseInt(document.getElementById(str).value);
for (let i2 = 0; i2 < n; i2++) {
str = "s" + i1 + i2 + "_t";
document.getElementById(str).style.display = "";
}
for (let i2 = n; i2 <= max_order; i2++) {
str = "s" + i1 + i2 + "_t";
document.getElementById(str).style.display = "none";
}
}
str = "b" + i1;
if (document.getElementById(str).value == "") {
for (let i2 = 0; i2 <= max_order; i2++) {
str = "b" + i1 + i2 + "_t";
document.getElementById(str).style.display = "none";
}
}
else {
let n = parseInt(document.getElementById(str).value);
for (let i2 = 0; i2 < n; i2++) {
str = "b" + i1 + i2 + "_t";
document.getElementById(str).style.display = "";
}
for (let i2 = n; i2 <= max_order; i2++) {
str = "b" + i1 + i2 + "_t";
document.getElementById(str).style.display = "none";
}
}
}
for (let i1 = n_g; i1 < max_g; i1++) {
str = "div" + i1;
document.getElementById(str).style.display = "none";
}
}
}
// 分子の次数
else if (sw == 1) {
str = "s" + kind;
if (document.getElementById(str).value == "") {
for (let i1 = 0; i1 <= max_order; i1++) {
str = "s" + kind + i1 + "_t";
document.getElementById(str).style.display = "none";
}
}
else {
let n = parseInt(document.getElementById(str).value);
for (let i1 = 0; i1 <= n; i1++) {
str = "s" + kind + i1 + "_t";
document.getElementById(str).style.display = "";
}
for (let i1 = n+1; i1 <= max_order; i1++) {
str = "s" + kind + i1 + "_t";
document.getElementById(str).style.display = "none";
}
}
}
// 分母の次数
else {
str = "b" + kind;
if (document.getElementById(str).value == "") {
for (let i1 = 0; i1 <= max_order; i1++) {
str = "b" + kind + i1 + "_t";
document.getElementById(str).style.display = "none";
}
}
else {
let n = parseInt(document.getElementById(str).value);
for (let i1 = 0; i1 <= n; i1++) {
str = "b" + kind + i1 + "_t";
document.getElementById(str).style.display = "";
}
for (let i1 = n+1; i1 <= max_order; i1++) {
str = "b" + kind + i1 + "_t";
document.getElementById(str).style.display = "none";
}
}
}
}
/**************/
/* 画面の構成 */
/**************/
function s_area()
{
for (let i1 = 0; i1 < max_g; i1++) {
document.write(' <DIV ID="div' + i1 + '" STYLE="font-size: 100%; text-align:center; background-color: #ffffff; width: 800px; height:200px; margin-right: auto; margin-left: auto; border: 1px green solid; overflow: auto">\n');
document.write(' ' + (i1+1) + ' 番目の式の説明:<INPUT ID="exp' + i1 + '" STYLE="font-size: 100%" TYPE="text" SIZE="15" VALUE=""><BR>\n');
document.write(' <DIV ID="div' + i1 + '1" STYLE="font-size: 100%; text-align:center; background-color: #eeffee; width: 395px; height:150px; border: 1px black solid; overflow: auto; float: left;">\n');
document.write(' ' + (i1+1) + '.分子の次数:<INPUT ID="s' + i1 + '" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="" onBlur="change(' + i1 + ',1)"><BR>\n');
document.write(' <SPAN ID="s' + i1 + '0_t">定数項:<INPUT ID="s' + i1 + '0" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE=""></SPAN><BR>\n');
for (let i2 = 1; i2 <= max_order; i2++)
document.write(' <SPAN ID="s' + i1 + i2 + '_t">s の ' + i2 + ' 次の項:<INPUT ID="s' + i1 + i2 + '" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE=""></SPAN><BR>\n');
document.write(' </DIV>\n');
document.write(' <DIV ID="div' + i1 + '2" STYLE="font-size: 100%; text-align:center; background-color: #eeffee; width: 395px; height:150px; border: 1px black solid; overflow: auto; float: right;">\n');
document.write(' ' + (i1+1) + '.分母の次数:<INPUT ID="b' + i1 + '" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="" onBlur="change(' + i1 + ',2)"><BR>\n');
document.write(' <SPAN ID="b' + i1 + '0_t">定数項:<INPUT ID="b' + i1 + '0" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE=""></SPAN><BR>\n');
for (let i2 = 1; i2 <= max_order; i2++)
document.write(' <SPAN ID="b' + i1 + i2 + '_t">s の ' + i2 + ' 次の項:<INPUT ID="b' + i1 + i2 + '" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE=""></SPAN><BR>\n');
document.write(' </DIV>\n');
document.write(' </DIV>\n');
}
}
</SCRIPT>
</HEAD>
<BODY STYLE="font-size: 130%; text-align:center; background-color: #eeffee;">
<H2 STYLE="text-align:center"><B>ボード線図</B></H2>
式の数(グラフの数):<INPUT ID="n_g" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="1" onBlur="change(-1, -1)">
<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="return main()">実行</BUTTON><BR><BR>
周波数下限:<INPUT ID="low" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="0.01">
周波数上限:<INPUT ID="up" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="100">
データ数:<INPUT ID="n_data" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="100"><BR><BR>
<DIV STYLE="font-size: 100%; text-align:center; background-color: #ffffff; width: 820px; height:300px; margin-right: auto; margin-left: auto; border: 2px green solid; padding: 5px; overflow: auto">
<SCRIPT TYPE="text/javascript">
s_area();
change(-1, -1);
</SCRIPT>
</DIV><BR>
<TEXTAREA ID="ans" COLS="70" ROWS="10" STYLE="font-size: 100%;"></TEXTAREA>
</BODY>
</HTML>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>グラフの表示</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
<LINK REL="stylesheet" TYPE="text/css" HREF="../master.css">
<SCRIPT TYPE="text/javascript" SRC="graph.js"></SCRIPT>
<SCRIPT TYPE="text/javascript">
function GetParameter()
{
let result = new Array();
if(1 < window.location.search.length) {
// 最初の1文字 (?記号) を除いた文字列を取得する
let str = window.location.search.substring(1);
// 区切り記号 (&) で文字列を配列に分割する
let param = str.split('&');
for(let i1 = 0; i1 < param.length; i1++ ) {
// パラメータ名とパラメータ値に分割する
let element = param[i1].split('=');
let Name = decodeURIComponent(element[0]);
let Value = decodeURIComponent(element[1]);
// パラメータ名をキーとして連想配列に追加する
result[Name] = Value;
}
}
return result;
}
</SCRIPT>
</HEAD>
<BODY CLASS="white" STYLE="text-align: center">
<DIV ID="cl_line" STYLE="text-align: center; display: none">
<FORM>
<DIV ID="c0">
<INPUT ID="rgb0" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r0" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(0)">
緑<INPUT ID="g0" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(0)">
青<INPUT ID="b0" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(0)">
</DIV>
<DIV ID="c1">
<INPUT ID="rgb1" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r1" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(1)">
緑<INPUT ID="g1" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(1)">
青<INPUT ID="b1" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(1)">
</DIV>
<DIV ID="c2">
<INPUT ID="rgb2" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r2" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(2)">
緑<INPUT ID="g2" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(2)">
青<INPUT ID="b2" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(2)">
</DIV>
<DIV ID="c3">
<INPUT ID="rgb3" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r3" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(3)">
緑<INPUT ID="g3" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(3)">
青<INPUT ID="b3" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(3)">
</DIV>
<DIV ID="c4">
<INPUT ID="rgb4" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r4" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(4)">
緑<INPUT ID="g4" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(4)">
青<INPUT ID="b4" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(4)">
</DIV>
<DIV ID="c5">
<INPUT ID="rgb5" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r5" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(5)">
緑<INPUT ID="g5" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(5)">
青<INPUT ID="b5" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(5)">
</DIV>
<DIV ID="c6">
<INPUT ID="rgb6" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r6" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(6)">
緑<INPUT ID="g6" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(6)">
青<INPUT ID="b6" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(6)">
</DIV>
<DIV ID="c7">
<INPUT ID="rgb7" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r7" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(7)">
緑<INPUT ID="g7" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(7)">
青<INPUT ID="b7" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(7)">
</DIV>
<DIV ID="c8">
<INPUT ID="rgb8" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r8" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(8)">
緑<INPUT ID="g8" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(8)">
青<INPUT ID="b8" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(8)">
</DIV>
<DIV ID="c9">
<INPUT ID="rgb9" TYPE="text" SIZE="3" STYLE="font-size: 90%">
赤<INPUT ID="r9" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(9)">
緑<INPUT ID="g9" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(9)">
青<INPUT ID="b9" TYPE="text" SIZE="1" STYLE="font-size: 90%" onblur="c_change(9)">
</DIV>
<DIV ID="line_m">
マーク:<INPUT ID="l_m1" TYPE="radio" NAME="mark" STYLE="font-size: 90%" CHECKED>付ける
<INPUT ID="l_m2" TYPE="radio" NAME="mark" STYLE="font-size: 90%">付けない
</DIV>
<DIV ID="line_w">
線の太さ:<INPUT ID="l_w" TYPE="text" SIZE="3" STYLE="font-size: 90%" VALUE="2">
</DIV>
<DIV>
<SPAN STYLE="background-color: pink; font-size: 100%" onClick="D_Change()">OK</SPAN>
</DIV>
</FORM>
</DIV>
<BR>
<DIV STYLE="text-align: center">
<CANVAS ID="canvas_e" STYLE="background-color: #eeffee;" WIDTH="900" HEIGHT="600" onClick="Click(event)"></CANVAS>
</DIV>
<SCRIPT TYPE="text/javascript">
let result = GetParameter();
graph(result['gp']);
</SCRIPT>
</BODY>
</HTML>
<?php
/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
class Complex {
public $r; // 実部
public $i; // 虚部
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
function Complex($a, $b = 0.0)
{
$this->r = $a;
$this->i = $b;
}
}
/******************/
/* 複素数の絶対値 */
/******************/
function abs_c($a)
{
return sqrt($a->r * $a->r + $a->i * $a->i);
}
/****************/
/* 複素数の角度 */
/****************/
function angle($a)
{
$x = 0.0;
if ($a->r != 0.0 || $a->i != 0.0)
$x = atan2($a->i, $a->r);
return $x;
}
/****************/
/* 複素数のn乗 */
/****************/
function pow_c($a, $n)
{
$c = new Complex(1.0);
if ($n >= 0) {
for ($i1 = 0; $i1 < $n; $i1++)
$c = mul($c, $a);
}
else {
for ($i1 = 0; $i1 < -$n; $i1++)
$c = mul($c, $a);
$c = div(new Complex(1.0), $c);
}
return $c;
}
/****************/
/* 複素数の加算 */
/****************/
function add($a, $b)
{
$c = new Complex(0.0);
$c->r = $a->r + $b->r;
$c->i = $a->i + $b->i;
return $c;
}
/****************/
/* 複素数の減算 */
/****************/
function sub($a, $b)
{
$c = new Complex(0.0);
$c->r = $a->r - $b->r;
$c->i = $a->i - $b->i;
return $c;
}
/****************/
/* 複素数の乗算 */
/****************/
function mul($a, $b)
{
$c = new Complex(0.0);
$c->r = $a->r * $b->r - $a->i * $b->i;
$c->i = $a->i * $b->r + $a->r * $b->i;
return $c;
}
/****************/
/* 複素数の除算 */
/****************/
function div($a, $b)
{
$c = new Complex(0.0);
$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;
}
/********************************************************************/
/* 伝達関数の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 : 結果 */
/********************************************************************/
function G_s($ff, $ms, $m, $si, $mb, $n, $bo)
{
// 周波数を複素数に変換
$f = new Complex(0.0, $ff);
// 分子
$x = value($f, $ms, $m, $si);
// 分母
$y = value($f, $mb, $n, $bo);
return div($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 : 結果 */
/****************************************************************/
function value($f, $ms, $n, $a)
{
$u0 = new Complex(0.0);
$u1 = new Complex(1.0);
// 因数分解されていない
if ($ms == 0) {
$x = $u0;
for ($i1 = 0; $i1 <= $n; $i1++)
$x = add($x, mul(new Complex($a[$i1]), pow_c($f, $i1)));
}
// 因数分解されている
else {
if ($n == 0)
$x = mul(new Complex($a[0]), $u1);
else {
$x = $u1;
$k1 = 2 * $n;
for ($i1 = 0; $i1 < $k1; $i1 += 2)
$x = mul($x, add(new Complex($a[$i1]), mul(new Complex($a[$i1+1]), $f)));
}
}
return $x;
}
/*******************/
/* main プログラム */
/*******************/
$phase = 0.0;
$uc = 90.0 / asin(1.0);
/*
データの入力
*/
// 出力ファイル名の入力とファイルのオープン
fscanf(STDIN, "%*s %s %*s %s", $o_fg, $o_fp);
$og = fopen($o_fg, "w");
$op = fopen($o_fp, "w");
// 伝達関数データ
fscanf(STDIN, "%*s %lf %lf %*s %d", $fl, $fu, $k);
// 分子
$str = trim(fgets(STDIN));
strtok($str, " ");
$ms = intval(strtok(" "));
strtok(" ");
$m = intval(strtok(" "));
strtok(" ");
$si = array();
// 因数分解されていない
if ($ms == 0) {
$k1 = $m + 1;
for ($i1 = 0; $i1 < $k1; $i1++)
$si[$i1] = floatval(strtok(" "));
}
// 因数分解されている
else {
$k1 = ($m == 0) ? 1 : 2 * $m;
for ($i1 = 0; $i1 < $k1; $i1++)
$si[$i1] = floatval(strtok(" "));
}
// 分母
$str = trim(fgets(STDIN));
strtok($str, " ");
$mb = intval(strtok(" "));
strtok(" ");
$n = intval(strtok(" "));
strtok(" ");
$bo = array();
// 因数分解されていない
if ($mb == 0) {
$k1 = $n + 1;
for ($i1 = 0; $i1 < $k1; $i1++)
$bo[$i1] = floatval(strtok(" "));
}
// 因数分解されている
else {
$k1 = ($n == 0) ? 1 : 2 * $n;
for ($i1 = 0; $i1 < $k1; $i1++)
$bo[$i1] = floatval(strtok(" "));
}
/*
ゲインと位相の計算
*/
$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_c($g));
$x = angle($g) * $uc;
while (abs($phase-$x) > 180.0) {
if ($x-$phase > 180.0)
$x -= 360.0;
else {
if ($x-$phase < -180.0)
$x += 360.0;
}
}
$phase = $x;
// 出力
fwrite($og, $f." ".$gain."\n");
fwrite($op, $f." ".$phase."\n");
// 次の周波数
$ff += $h;
}
/*
------------------------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
*/
?>
#*******************************/
# 伝達関数のゲインと位相の計算 */
# 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
#*******************************/
# 伝達関数のゲインと位相の計算 */
# 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
# -*- coding: UTF-8 -*- import numpy as np import sys import math import cmath ################################ # 伝達関数のゲインと位相の計算 # coded by Y.Suganuma ################################ ################################################################ # 多項式の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 range(0, n+1) : x = x + a[i1] * (f ** i1) # 因数分解されている else : if n == 0 : x = a[0] * u1 else : x = u1 k1 = 2 * n for i1 in range(0, k1, 2) : x = x * (a[i1] + a[i1+1] * f) return x #################################################################### # 伝達関数の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 phase = 0.0 # データの入力 # 出力ファイル名の入力とファイルのオープン line = sys.stdin.readline() s = line.split() o_fg = s[1] o_fp = s[3] og = open(o_fg, "w") op = open(o_fp, "w") # 伝達関数データ line = sys.stdin.readline() s = line.split() fl = float(s[1]) fu = float(s[2]) k = int(s[4]) # 分子 line = sys.stdin.readline() s = line.split() ms = int(s[1]) m = int(s[3]) # 因数分解されていない if ms == 0 : k1 = m + 1 si = np.empty(k1, np.float) for i1 in range(0, k1) : si[i1] = float(s[i1+5]) # 因数分解されている else : if m == 0 : k1 = 1 else : k1 = 2 * m si = np.empty(k1, np.float) for i1 in range(0, k1) : si[i1] = float(s[i1+5]) # 分母 line = sys.stdin.readline() s = line.split() mb = int(s[1]) n = int(s[3]) # 因数分解されていない if mb == 0 : k1 = n + 1 bo = np.empty(k1, np.float) for i1 in range(0, k1) : bo[i1] = float(s[i1+5]) # 因数分解されている else : if n == 0 : k1 = 1 else : k1 = 2 * n bo = np.empty(k1, np.float) for i1 in range(0, k1) : bo[i1] = float(s[i1+5]) # ゲインと位相の計算 h = (math.log10(fu) - math.log10(fl)) / k ff = math.log10(fl) for i1 in range(0, k+1) : # 周波数の対数を元に戻す f = 10.0 ** ff # 値の計算 g = G_s(f, ms, m, si, mb, n, bo) # ゲインと位相の計算 gain = 20.0 * math.log10(abs(g)) x = math.degrees(cmath.phase(g)) while abs(phase-x) > 180.0 : if x-phase > 180.0 : x -= 360.0 else : if x-phase < -180.0 : x += 360.0 phase = x # 出力 og.write(str(f) + " " + str(gain) + "\n") op.write(str(f) + " " + str(phase) + "\n") # 次の周波数 ff += h og.close() op.close() """ ------------------------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 """
/********************************/
/* 伝達関数のゲインと位相の計算 */
/* coded by Y.Suganuma */
/********************************/
using System;
using System.IO;
class Program
{
/****************/
/* main program */
/****************/
static void Main(String[] args)
{
double uc = 90.0 / Math.Asin(1.0);
char[] charSep = new char[] {' '};
//
// データの入力
//
// 出力ファイル名とファイルのオープン
String[] str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
StreamWriter g_o = new StreamWriter(str[1]);
StreamWriter p_o = new StreamWriter(str[3]);
// 伝達関数データ
str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
double fl = double.Parse(str[1]);
double fu = double.Parse(str[2]);
int k = int.Parse(str[4]);
// 分子
str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
int ms = int.Parse(str[1]);
int m = int.Parse(str[3]);
// 因数分解されていない
double[] si;
if (ms == 0) {
int k1 = m + 1;
si = new double [k1];
for (int i1 = 0; i1 < k1; i1++)
si[i1] = double.Parse(str[i1+5]);
}
// 因数分解されている
else {
int k1 = (m == 0) ? 1 : 2 * m;
si = new double [k1];
for (int i1 = 0; i1 < k1; i1++)
si[i1] = double.Parse(str[i1+5]);
}
// 分母
str = Console.ReadLine().Split(charSep, StringSplitOptions.RemoveEmptyEntries);
int mb = int.Parse(str[1]);
int n = int.Parse(str[3]);
// 因数分解されていない
double[] bo;
if (mb == 0) {
int k1 = n + 1;
bo = new double [k1];
for (int i1 = 0; i1 < k1; i1++)
bo[i1] = double.Parse(str[i1+5]);
}
// 因数分解されている
else {
int k1 = (n == 0) ? 1 : 2 * n;
bo = new double [k1];
for (int i1 = 0; i1 < k1; i1++)
bo[i1] = double.Parse(str[i1+5]);
}
//
// インと位相の計算
//
double h = (Math.Log10(fu) - Math.Log10(fl)) / k;
double ff = Math.Log10(fl);
double phase = 0.0;
for (int i1 = 0; i1 <= k; i1++) {
// 周波数の対数を元に戻す
double f = Math.Pow(10.0, ff);
// 値の計算
Complex g = G_s(f, ms, m, si, mb, n, bo);
// ゲインと位相の計算
double gain = 20.0 * Math.Log10(Complex.abs(g));
double x = Complex.angle(g) * uc;
while (Math.Abs(phase-x) > 180.0) {
if (x-phase > 180.0)
x -= 360.0;
else {
if (x-phase < -180.0)
x += 360.0;
}
}
phase = x;
// 出力
g_o.WriteLine(f + " " + gain);
p_o.WriteLine(f + " " + phase);
// 次の周波数
ff += h;
}
g_o.Close();
p_o.Close();
}
/********************************************************************/
/* 伝達関数の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 : 結果 */
/********************************************************************/
static Complex G_s(double ff, int ms, int m, double[] si, int mb, int n, double[] bo)
{
// 周波数を複素数に変換
Complex f = new Complex (0.0, ff);
// 分子
Complex x = value(f, ms, m, si);
// 分母
Complex y = value(f, mb, n, bo);
return Complex.dev(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 : 結果 */
/****************************************************************/
static Complex value(Complex f, int ms, int n, double[] a)
{
Complex x;
// 因数分解されていない
if (ms == 0) {
x = new Complex (0.0, 0.0);
for (int i1 = 0; i1 <= n; i1++)
x = Complex.add(x, Complex.mul(new Complex(a[i1]), Complex.pow(f, i1)));
}
// 因数分解されている
else {
if (n == 0)
x = new Complex (a[0]);
else {
x = new Complex (1.0, 0.0);
int k1 = 2 * n;
for (int i1 = 0; i1 < k1; i1 += 2)
x = Complex.mul(x, Complex.add(new Complex(a[i1]), Complex.mul(new Complex(a[i1+1]), f)));
}
}
return x;
}
}
/****************************/
/* クラスComplex */
/* coded by Y.Suganuma */
/****************************/
class Complex {
double r; // 実部
double i; // 虚部
/******************/
/* コンストラクタ */
/* a : 実部 */
/* b : 虚部 */
/******************/
public Complex(double a = 0.0, double b = 0.0)
{
r = a;
i = b;
}
/********/
/* 出力 */
/********/
public void output(StreamWriter OUT, Complex a)
{
OUT.Write("(" + a.r + ", " + a.i + ")");
}
/******************/
/* 複素数の絶対値 */
/******************/
public static double abs(Complex a)
{
return Math.Sqrt(a.r * a.r + a.i * a.i);
}
/****************/
/* 複素数の角度 */
/****************/
public static double angle(Complex a)
{
double x = 0.0;
if (a.r != 0.0 || a.i != 0.0)
x = Math.Atan2(a.i, a.r);
return x;
}
/****************/
/* 複素数のn乗 */
/****************/
public static Complex pow(Complex a, int n)
{
Complex c = new Complex (1);
if (n >= 0) {
for (int i1 = 0; i1 < n; i1++)
c = Complex.mul(c, a);
}
else {
for (int i1 = 0; i1 < -n; i1++)
c = Complex.mul(c, a);
c = Complex.dev(new Complex(1.0), c);
}
return c;
}
/****************/
/* 複素数の加算 */
/****************/
public static Complex add(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
/****************/
/* 複素数の減算 */
/****************/
public static Complex sub(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
/****************/
/* 複素数の乗算 */
/****************/
public static Complex mul(Complex a, Complex b)
{
Complex c = new Complex();
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
/****************/
/* 複素数の除算 */
/****************/
public static Complex dev(Complex a, Complex b)
{
Complex c = new Complex();
double 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;
}
}
/*
------------------------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
*/
'******************************'
' 伝達関数のゲインと位相の計算 '
' coded by Y.Suganuma '
'******************************'
Imports System.IO
Imports System.Text.RegularExpressions
Module Test
Sub Main()
Dim uc As Double = 90.0 / Math.Asin(1.0)
'
' データの入力
'
' 出力ファイル名とファイルのオープン
Dim MS1 As Regex = New Regex("\s+")
Dim str() As String = MS1.Split(Console.ReadLine().Trim())
Dim g_o As StreamWriter = new StreamWriter(str(1))
Dim p_o As StreamWriter = new StreamWriter(str(3))
' 伝達関数データ
str = MS1.Split(Console.ReadLine().Trim())
Dim fl As Double = Double.Parse(str(1))
Dim fu As Double = Double.Parse(str(2))
Dim k As Integer = Integer.Parse(str(4))
' 分子
str = MS1.Split(Console.ReadLine().Trim())
Dim ms As Integer = Integer.Parse(str(1))
Dim m As Integer = Integer.Parse(str(3))
' 因数分解されていない
Dim si() As Double
If ms = 0
Dim k1 As Integer = m + 1
ReDim si(k1)
For i1 As Integer = 0 To k1-1
si(i1) = Double.Parse(str(i1+5))
Next
' 因数分解されている
Else
Dim k1 As Integer
If m = 0
k1 = 1
Else
k1 = 2 * m
End If
ReDim si(k1)
For i1 As Integer = 0 To k1-1
si(i1) = Double.Parse(str(i1+5))
Next
End If
' 分母
str = MS1.Split(Console.ReadLine().Trim())
Dim mb As Integer = Integer.Parse(str(1))
Dim n As Integer = Integer.Parse(str(3))
' 因数分解されていない
Dim bo() As Double
If mb = 0
Dim k1 As Integer = n + 1
ReDim bo(k1)
For i1 As Integer = 0 To k1-1
bo(i1) = Double.Parse(str(i1+5))
Next
' 因数分解されている
Else
Dim k1 As Integer
If n = 0
k1 = 1
Else
k1 = 2 * n
End If
ReDim bo(k1)
For i1 As Integer = 0 To k1-1
bo(i1) = Double.Parse(str(i1+5))
Next
End If
'
' インと位相の計算
'
Dim h As Double = (Math.Log10(fu) - Math.Log10(fl)) / k
Dim ff As Double = Math.Log10(fl)
Dim phase As Double = 0.0
For i1 As Integer = 0 To k
' 周波数の対数を元に戻す
Dim f As Double = Math.Pow(10.0, ff)
' 値の計算
Dim g As Complex = G_s(f, ms, m, si, mb, n, bo)
' ゲインと位相の計算
Dim gain As Double = 20.0 * Math.Log10(g.abs())
Dim x As Double = g.angle() * uc
Do While Math.Abs(phase-x) > 180.0
If x-phase > 180.0
x -= 360.0
Else
If x-phase < -180.0
x += 360.0
End If
End If
Loop
phase = x
' 出力
g_o.WriteLine(f & " " & gain)
p_o.WriteLine(f & " " & phase)
' 次の周波数
ff += h
Next
g_o.Close()
p_o.Close()
End Sub
'******************************************************************'
' 伝達関数の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 : 結果 '
'******************************************************************'
Function G_s(ff As Double, ms As Integer, m As Integer, si() As Double, mb As Integer, n As Integer, bo() As Double)
' 周波数を複素数に変換
Dim f As Complex = new Complex (0.0, ff)
' 分子
Dim x As Complex = value(f, ms, m, si)
' 分母
Dim y As Complex = value(f, mb, n, bo)
Return c_dev(x, y)
End Function
'**************************************************************'
' 多項式の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 : 結果 '
'**************************************************************'
Function value(f As Complex, ms As Integer, n As Integer, a() As Double)
Dim x As Complex
' 因数分解されていない
If ms = 0
x = new Complex (0.0, 0.0)
For i1 As Integer = 0 To n
x = c_add(x, c_mul(new Complex(a(i1)), c_pow(f, i1)))
Next
' 因数分解されている
Else
If n = 0
x = new Complex (a(0))
Else
x = new Complex (1.0, 0.0)
Dim k1 As Integer = 2 * n
For i1 As Integer = 0 To k1-1 Step 2
x = c_mul(x, c_add(new Complex(a(i1)), c_mul(new Complex(a(i1+1)), f)))
Next
End If
End If
Return x
End Function
'**************'
' 複素数のn乗 '
'**************'
Function c_pow(a As Complex, n As Integer)
Dim c As Complex = new Complex (1)
If n >= 0
For i1 As Integer = 0 To n-1
c = c_mul(c, a)
Next
Else
For i1 As Integer = 0 To -n-1
c = c_mul(c, a)
Next
c = c_dev(new Complex(1.0), c)
End If
Return c
End Function
'**************'
' 複素数の加算 '
'**************'
Function c_add(a As Complex, b As Complex)
Dim c As Complex = new Complex()
c.r = a.r + b.r
c.i = a.i + b.i
Return c
End Function
'**************'
' 複素数の減算 '
'**************'
Function c_sub(a As Complex, b As Complex)
Dim c As Complex = new Complex()
c.r = a.r - b.r
c.i = a.i - b.i
Return c
End Function
'**************'
' 複素数の乗算 '
'**************'
Function c_mul(a As Complex, b As Complex)
Dim c As Complex = new Complex()
c.r = a.r * b.r - a.i * b.i
c.i = a.i * b.r + a.r * b.i
Return c
End Function
'**************'
' 複素数の除算 '
'**************'
Function c_dev(a As Complex, b As Complex)
Dim c As Complex = new Complex()
Dim x As Double = 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
End Function
'**************************'
' クラスComplex '
' coded by Y.Suganuma '
'**************************'
Class Complex
Public r As Double ' 実部
Public i As Double ' 虚部
'****************'
' コンストラクタ '
' a : 実部 '
' b : 虚部 '
'****************'
Public Sub New(Optional a As Double = 0.0, Optional b As Double = 0.0)
r = a
i = b
End Sub
'******'
' 出力 '
'******'
Sub output(OUT As StreamWriter)
OUT.Write("(" & r & ", " & i & ")")
End Sub
'****************'
' 複素数の絶対値 '
'****************'
Public Function abs()
Return Math.Sqrt(r * r + i * i)
End Function
'**************'
' 複素数の角度 '
'**************'
Public Function angle()
Dim x As Double = 0.0
If r <> 0.0 or i <> 0.0
x = Math.Atan2(i, r)
End If
Return x
End Function
End Class
End Module
/*
------------------------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
*/
| 情報学部 | 菅沼ホーム | 目次 | 索引 |