MPFRライブラリに、複素数も扱えるようにしたMPCライブラリ。最近複素数を使いたいと思うケースがあったので、前回の記事を参考にテストしてみました。
通常、複素数演算は実部と虚部を分けて計算すればいいのですが、累乗に複素数を使うようなイメージがしにくい計算では、このようなライブラリが有効なのではと思います。
そこで、下記はこれを使う有名なオイラーの公式ですが、これをライブラリで計算してみることにします。
xにπを代入すると、世界でもっとも美しいといわれる公式になります。
両辺とも直接的な関係はないのですが、それぞれテーラー展開という無限級数にして計算すると一致するという不思議な関係です。
虚数乗というなんと解釈していいかわからないようなものでも、数学の世界では表現できるという、ここが面白いところです。
環境: Ubuntu 18.04
インストール・ビルド
sudo apt install libmpc-dev
cc -o euler euler.c -lmpc -lmpfr -lgmp
euler.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
#include <stdio.h> #include <mpc.h> int main() { mpfr_t pi, sn; mpc_t work, e, re1, im1, ipi; mpfr_init2(pi, 128); mpfr_init2(sn, 128); mpc_init2(work, 128); mpc_init2(e, 128); mpc_init2(ipi, 128); mpc_init2(re1, 128); mpc_init2(im1, 128); mpc_set_ui_ui(re1, 1, 0, MPC_RNDNN); mpc_set_ui_ui(im1, 0, 1, MPC_RNDNN); mpc_exp(e, re1, MPC_RNDDD); mpfr_const_pi(pi, MPFR_RNDD); mpc_out_str(stdout, 10, 0, e, MPC_RNDDD); printf("\n"); mpfr_out_str(stdout, 10, 0, pi, MPFR_RNDD); printf("\n"); mpc_mul_fr(ipi, im1, pi, MPC_RNDDD); mpc_pow(work, e, ipi, MPC_RNDNN); mpc_out_str(stdout, 10, 0, work, MPC_RNDDD); printf("\n"); mpfr_sin(sn, pi, MPFR_RNDD); mpfr_out_str(stdout, 10, 0, sn, MPFR_RNDD); printf("\n"); mpc_clear(work); ; return 0; } |
結果
(2.718281828459045235360287471352662497747 0)
3.141592653589793238462643383279502884195
(-1.000000000000000000000000000000000000000 1.338432504205046150309804279711632522358e-38)
1.883041077660785116745909548456034940273e-39
まず演算に使う、虚数単位(im1)、ネイピア数e、と円周率piを用意します。(eにmpfr_const_eみたいなものがない?)
re1はeの値を導き出すために使います。
結果の3行目が、求めたい値です。実部は-1で問題ないですが、虚部は0にならずかなり小さい数となっています。sin(π)も単独で演算してみましたが、一致はしませんでした。
コンピュータの計算では当然誤差がでてくるため、その範囲としますが、一桁違うのはちょっと気になります。
複素数型なのかどうかヘッダーファイルにある関数の型とにらめっこして慎重に型変換をしていきました。
なかなか手間ですが、やっていることがわかりやすく応用を考えたとき、各種ラッパーライブラリよりも使いやすいと思っています。