Multiple Precision Floating-Point Reliable Library と長い名前のこのライブラリ。高品質多倍長浮動小数点ライブラリというらしいですが、簡単にいえば何百桁ともいう数の演算をすることができます。
よく数学の世界で、最大の素数を発見、または円周率何桁まで計算、などと話題になったりしますが、具体的にはどうやって計算しているのだろうかと、興味をもったことがありました。スーパーコンピュータで専用のプログラムを使って計算するのでしょうが、このライブラリを使えばそのエッセンスを味わうことができます。
その前に現在の標準的な64bitコンピュータで扱える演算精度を確認したいと思います。
1 2 3 4 5 6 7 8 9 10 11 |
#include<stdio.h> int main() { long n1 = 0xffffffffffffffff; printf("%lu : %ld\n", n1, n1); double d1 = 1.0, d2 = 3.0, d3; d3 = d1 / d2; printf("%.20lf\n", d3); } |
18446744073709551615 : -1
0.33333333333333331483
64bit unsignedの整数で20桁、浮動小数仮数部52bitで16桁の有効桁を確認できます。
実用的にはこれで十分な桁数がありますが、数学の世界では無限に必要となるようです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <stdio.h> #include <stdlib.h> #include <gmp.h> #include <mpfr.h> int main() { mpfr_t n1, n2; mpfr_init2(n1, 200); mpfr_init2(n2, 200); mpfr_set_str(n1, "1111111111111111111111111", 10, MPFR_RNDD); mpfr_mul(n2, n1, n1, MPFR_RNDD); mpfr_out_str(stdout, 10, 0, n2, MPFR_RNDD); printf("\n"); mpfr_clear(n1); mpfr_clear(n2); return 0; } |
1.2345679012345679012345676543209876543209876543210000000000000e48
200bitの精度の整数を掛け算した結果です。桁数が多いとC言語の数字として表現できないので文字列にして初期化しています。
次に円周率です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <stdio.h> #include <stdlib.h> #include <gmp.h> #include <mpfr.h> int main() { mpfr_t pi; mpfr_init2(pi, 2000); mpfr_const_pi(pi, MPFR_RNDD); mpfr_out_str(stdout, 10, 0, pi, MPFR_RNDD); printf("\n"); mpfr_clear(pi); } |
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405131995
2000bitの精度で初期化し、πを求める関数があるのでそれを利用しました。
このくらいだとすぐに結果を出してくれます。(もっといけますが、結果が長すぎるで・・、素数判定は64bitでかなり遅いので、これを使うレベルでない)
たまにはPCもこういう使い方すると、スペックの進化も実感することができます。
環境: Ubuntu 18.04
https://www.mpfr.org/