2010. 6. 2.
2014. 2.10. System.Numerics への参照方法を追加
石立 喬
Visual C++ 2010 Express の易しい使い方(10)
―――標準C++ライブラリのcomplexクラスを使用し、複素数計算の結果をグラフに表す―――
Visual C++ 2010 Express を使って、電気技術者向きのプログラムを作ってみた。電気回路では、インピーダンスの計算などで面倒な複素数計算が必要になるので、複素数計算を簡単にするために、標準C++ライブラリのcomplexクラスを使用した。一例として、適当な値を持った抵抗、コイル、コンデンサの直列回路に交流信号を流したとき、コンデンサの両端の電圧を計算し、横軸を対数目盛の周波数に、縦軸をデシベルで表し、グラフ化する場合を紹介する。
Visual C++ 2010は .NET Framework 4.0を使用していて、これにはComplex構造体が新たに導入されている。ただし、これを利用するには、System.Numerics.dllへの参照を追加する必要がある。方法については、末尾を参照されたい。
使用する電気回路と式
図1のような、抵抗R、コイルL、コンデンサCの直列回路で、交流の入力電圧をこの直列回路に加えたとき、コンデンサの両端の電圧を出力電圧として求める。
図1 LCR直列回路
出力電圧/入力電圧を伝達係数と考えて、それを求める式を下記に示す。結局、実数部が(1-ω2LC)で虚数部がωCRの複素数で1を割れば良いことになる。このプログラムでは、分子と分母をそれぞれ複素数と考え、二つの複素数の割り算を行う。
C++標準のcomplexクラスの使い方
◎ヘッダ
#include <complex> を #pragma once の下に記述する。
◎名前空間
C++ の標準ライブラリに含まれているので、using
namespace std; が必要である。
◎コンストラクタ
complex<double> z;
complex<double> z(real,imag);
などを使用する。
◎複素数の実数部、虚数部を設定する
zを複素数とすると、z.real(x) で実数部を、z.imag(y) で虚数部を設定することができる。
◎実数部、虚数部などのフィールドを取得する
zを複素数とすると、z.real() で実数部を、z.imag() で虚数部を取得することができる。
◎複素数間の演算
z1、z2、z3を複素数とすると、
z3=z1+z2;
z3=z1*z2;
z1/=z2; (z1=z1/z2 と同じ)
などが使える。
インピーダンスz1とインピーダンスz2を並列接続した時のインピーダンスは、
z3=1.0/(1.0/z1+1.0/z2);
を変形した、
z3=z1*z2/(z1+z2);
で求めることができる。
プログラムの概要
グラフの座標の作成は、横軸に対数目盛を使用しているので、decade
(10倍ごとの大きな目盛、インデックスはd)と、各
decade 内のlog101からlog1010まで(インデックスはf)とに分けて描画した。
グラフの描画は、単に数式に忠実に従っただけであって、特別の解説は要らないと思う。複素数z_oneは定数として使用し、複素数zは、フィールドz_realとz_imagから設定した。比率
ratio は、complexクラスの除算で求めた。
デシベル計算は、電圧比の場合、20*Math::Log10(ratio) で求めるが、描画の都合上、さらに5倍してある。
プログラム
◎Form1.hの頭に下記のように記述する
#pragma once
#include <complex>
using namespace std;
標準C++関係には、図2のようにIntelliSenseが効くので、それを使用した。

図2 ヘッダー・リストから「complex」を選ぶ
◎Form1_Paint()の内容
private: System::Void Form1_Paint(System::Object^ sender,
System::Windows::Forms::PaintEventArgs^
e) {
Graphics^ g=e->Graphics;
int X0=50,Y0=30,Y1=180,Y2=380;
int DECADE=6;
int d,f,i;
int x,y,old_x,old_y;
array<String^>^ horiscale={" 1","10","100","1k","10k","100k","1M"};
array<String^>^ vertscale={" 60dB"," 40dB"," 20dB"," 0dB","-20dB","-40dB","-60dB","-80dB"};
double ratio_abs;
double frequency,omega,resistance,inductance,capacitance;
complex<double> z_one(1.0,0.0); //定数1
complex<double> z;
complex<double> ratio;
resistance=1.0; //R=1Ω
inductance=1.0E-3; //L=1mH
capacitance=1.0E-8; //C=0.01uF
//縦線を引く
for(d=0;d<DECADE;d++)
for(f=1;f<=10;f++)
g->DrawLine(Pens::Black,X0+(int)((d+Math::Log10(f))*100),
Y2,X0+(int)((d+Math::Log10(f))*100),Y0);
//横線を引く
for(i=0;i<8;i++)
g->DrawLine(Pens::Black,X0,Y2-i*50,X0+DECADE*100,Y2-i*50);
//横軸の目盛を入れる
for(i=0;i<=DECADE;i++){
if(i==DECADE)
g->DrawString(horiscale[i]+" Hz",Font,Brushes::Black,40+i*100,Y2+10);
else
g->DrawString(horiscale[i],Font,Brushes::Black,40+i*100,Y2+10);
}
//縦軸の目盛を入れる
for(i=0;i<8;i++)
g->DrawString(vertscale[i],Font,Brushes::Black,5,Y0-8+i*50);
//比率のグラフを描く
for(d=0;d<DECADE;d++)
for(f=10;f<100;f++){
frequency=f/10.0*Math::Pow(10,d);
omega=2.0*Math::PI*frequency; //ω=2πf
z_real=1.0-omega*omega*inductance*capacitance; //1-ω2LC
z_imag=omega*capacitance*resistance; //ωCR
z.real(z_real);
z.imag(z_imag);
ratio=z_one/z;
//1/((1-ω2LC)+jωCR)
ratio_abs=abs(ratio);
if(d==0 && f==10){
old_x=X0;
old_y=Y1-(int)(Math::Log10(ratio_abs)*50);
}
else{
x=X0+(int)((d+Math::Log10(f/10.0))*100);
y=Y1-(int)(Math::Log10(ratio_abs)*50);
g->DrawLine(Pens::Red,old_x,old_y,x,y);
old_x=x;
old_y=y;
}
}
}
得られた画面
結果を図3に示す。共振周波数fは、

で計算でき、これは50.33kHzになるので、良く一致している。
図3 得られた周波数特性
System.Numerics.dll への参照を追加する方法
1)ソリューションエクスプローラで、<プロジェクト名>を右クリックする。
2)「追加」→「参照」を選択する。
3)「参照マネージャ」ダイアログボックスが開くので、
4)「System.Numerics」を選択し、左側のチェックボックスにチェックを入れる。
5)「OK」をクリックする。
プログラムに、using System.Numerics; を記述する。
「Visual C++ の勉強部屋」(目次)へ