pythonistaがC++で複素数を扱ってみる.

目次

はじめに

どうも,かわつあんです. 今日はpython歴2年の私がC++複素数をつかっていろいろしたいと思います.

複素数は今日の物理の計算や工学などでは必要不可欠なものとなっています. 私がC++で最終的にやりたい計算も複素数を扱いますので,実際に複素数を扱ってみて思ったことをまとめれたらと思います.

複素数とは

基本的にほとんどの人が知ってそうですが,簡単にまとめておきます.(厳密な説明ではないです.)

複素数とは,実数で扱えない計算を扱えるように拡張した数です. 普通は負の数の平方根は存在しませんが,複素数では虚数{i=\sqrt{-1}}を導入することで,負の数の平方根を扱えるようにしました. 複素数{z}は実部と虚部からなり,それぞれを{a, b}とすると{z = a + ib}のように書きます.

書き出したらキリがないので,このくらいにしておきます. 詳しくはwikiなどをどうぞ.

ja.wikipedia.org

C++複素数を扱う

それでは,C++複素数について扱おうと思いますが,pythonとの比較も行なっていこうと思います. 以下では,pythonで先にコードを作成および実行し,その後それと等価のことをC++で行なっていきます.

python複素数{4+3i}を出力してみます.

a = 4 + 3j
print(a)

実行結果

(1+1j)

このようにpythonでは,虚数単位をjで表します.これは,工学系では電流(密度)をiとして扱うことが多いため代わりに虚数単位をjとして表現する思想からきているようです. (ちなみに理学系では逆に電流をjと書くことが多いです)

次にC++複素数{4+3i}出力します.

#include <iostream>
#include <complex>
using namespace ::std;

int main(){
    complex<float> a;
    a = complex<float>(4,3);
    cout << a << endl;
}

実行結果

(4,3)

C++では(実部, 虚部)のようにして複素数を扱うようです.またcomplexクラスをインクルードしないと複素数を定義できません. すこし面倒ですが,そもそもCやC++複素数を扱う前提ではなかったみたいなのでしょうがないとは思います.

ここでは,complex<float>としており,複素数の実部および虚部はそれぞれfloat型にしていますが,intdoubleにもできます.(int型で複素数をあつかうのはあまり現実的ではありませんが.)

四則演算

複素数の演算もいろいろ行なってみます. まずは四則演算です.

pythonだと

a = 4 + 3j
b = 5 + 5j

print("{} + {} = {}".format(a, b, a+b))
print("{} - {} = {}".format(a, b, a-b))
print("{} * {} = {}".format(a, b, a*b))
print("{} / {} = {}".format(a, b, a/b))

実行結果

(4+3j) + (5+5j) = (9+8j)
(4+3j) - (5+5j) = (-1-2j)
(4+3j) * (5+5j) = (5+35j)
(4+3j) / (5+5j) = (0.7-0.1j)

バッチリです.手計算とも相違ないので,問題なさそうです.

続いてC++だと

#include <iostream>
#include <complex>
using namespace ::std;

int main(){
    complex<float> a,b;
    a = complex<float>(4,3);
    b = complex<float>(5,5);

    cout << a <<" + "<< b <<" = "<< a+b << endl;
    cout << a <<" - "<< b <<" = "<< a-b << endl;
    cout << a <<" * "<< b <<" = "<< a*b << endl;
    cout << a <<" / "<< b <<" = "<< a/b << endl;

}

出力結果

(4,3) + (5,5) = (9,8)
(4,3) - (5,5) = (-1,-2)
(4,3) * (5,5) = (5,35)
(4,3) / (5,5) = (0.7,-0.1)

問題なく計算できました!

複素数特有の計算

四則演算の次は,複素数特有の計算をしてみます. 具体的には{z = a + bi}としたときの 実部と虚部{Re(z) = a}{Im(z) = b}複素数の大きさ{|z|}偏角{arg(z)}複素共役{z* = a - bi}です.ここら辺が計算できれば,大体の計算はできると思います.

それではいきましょう.まずはpythonから.

import cmath
z = 4 + 3j
print("Re(z)  = {}".format(z.real))
print("Im(z)  = {}".format(z.imag))
print("|z|    = {}".format(abs(z)))
print("arg(z) = {}".format(cmath.phase(z)))
print("z*     = {}".format(z.conjugate())

比較的に簡単に計算できました. 偏角だけはモジュールでの関数がないみたいですね. numpyを使うといろいろ使えるmethodも変わりますが,ここでは割愛します.

#include <iostream>
#include <complex>
using namespace ::std;

int main(){
    complex<float> z;
    z = complex<float>(4,3);

    cout << "Re(z)  = " << z.real() << endl;
    cout << "Im(z)  = " << z.imag() << endl;
    cout << "|z|    = " << abs(z)   << endl;
    cout << "arg(z) = " << arg(z)   << endl;
    cout << "z*     = " << conj(z)  << endl;
}

実行結果

Re(z)  = 4
Im(z)  = 3
|z|    = 5
arg(z) = 0.643501
z*     = (4,-3)

計算できました.complexをインクルードしてしまったら,大体の計算ができるみたいでいいですね! 複素数特有の演算は慣れてしまえばC++でも簡単にできそうでよかったです.

さいごに

今回はC++複素数を扱って,いろいろな計算をしました.pythonのコードと適宜比較しましたが,少しの差異はあれども,C++でもそんなに難しくなく計算ができそうなので,ほっとしています.

次回は,複素数と配列を組み合わせた複素数配列を少しだけ扱ってみようと思います. 次回が終われば,ひとまずC++の演算の確認は終了して,ctypesにも触れて行こうと思います. どうぞお付き合いください〜

ではまた(✿╹◡╹)