任意精度計算ライブラリ(GMP)の使い方

プログラミング時に注意すべき点の一つに,計算精度の問題があります.

たとえばC/C++だと,doubleで計算しても有効桁数は15桁程度(10進数で)しかありません.その結果,以下のような状況で間違った計算結果が出てしまいます.

取り扱う数値が15桁を越える場合
取り扱う数値が7桁を越える場合
たとえば8桁同士の掛け算が行われるとその結果は最大16桁になります.double型の変数には15桁程度の情報しか保存できないので,下位1桁の情報は棄てられます.
取り扱う数値の最大値と最小値に,15桁の以上の差がある場合
たとえばC言語のdouble型で(1.0 + 1e-16)を計算すると結果は 1.0 になります.

これら計算精度の問題を避ける方法の一つにGMPというライブラリを使う方法があります。以下ポイントをまとめます。

GMPとは

GMP(GNU Multiple Precision library)とは任意精度計算ライブラリの一つです。GMPを使うと、変数単位で精度を指定することができ、上記のような計算精度の問題が解決できます。

ソースコード、ドキュメント等は http://gmplib.org/ で公開されています。

サンプルコードとコンパイル方法

たとえば以下のサンプルコードは、

$ gcc -lgmp hoge.c -o hoge

でコンパイルできます。

#include <stdio.h>
#include <gmp.h>
#define BASE 10
int
main()
{
    mpz_t a;
    mpz_init(a);
    mpz_set_str(a, "12345678901234567890", BASE);
    mpz_out_str (stdout, BASE, a); 
    printf("\n");
    mpz_clear(a);
    return 0;
}

APIの概要

変数の型

GMPでは、数値を格納する変数型として

の3つを用意しています.

変数の初期化

変数は初期化が必要です.

  mpz_t num;
  mpz_init(num);

また、精度を明示する場合は

  mpz_t num;
  mpz_init2(num, 512);

とします。この場合512bit分の精度が保証されます。

変数への数値の代入

代入する際は,数値を文字列で指定します.(文字列なので何桁の数値でも指定できます)

たとえば10進数の"12345"を num に保存する場合は次のように書きます。

  mpz_t num;
  mpz_init(num);
  mpz_set_str(num, "12345", 10);
数値計算

大抵の演算は定義済です。

  • mpz_add(z,x,y) z = x+y
  • mpz_sub(z,x,y) z = x-y
  • mpz_mul(z,x,y) z = x*y

関数一覧は GNU MP 6.1.2: Function Index にあります。

値の表示

変数 num の値を 10進数で stdout に出力する場合は以下のように記述します

  mpz_out_str(stdout, 10, num);


数値計算の常識
伊理 正夫 藤野 和建
共立出版
売り上げランキング: 93719