Skip to content

Latest commit

 

History

History
386 lines (285 loc) · 15.7 KB

multiprec-float.md

File metadata and controls

386 lines (285 loc) · 15.7 KB

多倍長浮動小数点数

多倍長浮動小数点数を使用するには、Boost Multiprecision Libraryを使用する。

インデックス

ここでは、Boost.Multiprecisionから提供される多倍長浮動小数点数の、基本的な使い方を示す。

以下は、任意精度の符号あり多倍長整数であるboost::multiprecision::cpp_dec_float_100クラス型を使用して、2の平方根を求めるプログラムである。

#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>

namespace mp = boost::multiprecision;

int main()
{
    // 型がサポートする10進数の桁数が100で、数の指数を表す符号付き整数型がboost::int32_t(32bit)の浮動小数点数
    mp::cpp_dec_float_100 x = 2.0f;

    // 平方根を求める
    mp::cpp_dec_float_100 result = mp::sqrt(x);

    // 出力桁数を設定して出力
    std::cout << std::setprecision(std::numeric_limits<decltype(x)>::digits10 + 1)
              << result;
}
  • cpp_dec_float_100 x = 2.0f;[color ff0000]

出力:

1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727

Boost.Multiprecisionの多倍長浮動小数点数は、以下の演算をサポートする。ビット演算は使用できない。

説明
a + b;
a += b;
加算
a - b;
a -= b;
減算
a * b;
a *= b;
乗算
a / b;
a /= b;
除算
+a; 符号をプラスにする
-a; 符号をマイナスにする
a++;
++a;
インクリメント
a--;
--a;
デクリメント
a == b; 等値比較
a != b; 非等値比較
a < b; abより小さいかの判定
a <= b; ab以下かの判定
a > b; abより大きいかの判定
a >= b; ab以上かの判定
os << a; ストリームへの出力
is >> a; ストリームからの入力

以下に、Boost.Multiprecisionから提供される多倍長整数の種類を示す。

Boost Multiprecision独自実装の多倍長浮動小数点数

#include <boost/multiprecision/cpp_dec_float.hpp>
説明
cpp_dec_float_50 10進数の桁数が50の浮動小数点数型
cpp_dec_float_100 10進数の桁数が100の浮動小数点数型

以下は、ユーザー定義の固定精度浮動小数点数型を定義する例である:

// 10進数の桁数が1,000の浮動小数点数の定義
namespace mp = boost::multiprecision;
typedef mp::number<mp::cpp_dec_float<1000> > cpp_dec_float_1000;

// 10進数の桁数が1,000、数の指数を表す符号付き整数型がstd::int64_t(64bit)の浮動小数点数の定義
// テンプレートの第二引数は、少なくとも2バイトで16ビット幅の組み込みの符号付き整数型を指定する
namespace mp = boost::multiprecision;
typedef mp::number<mp::cpp_dec_float<1000, std::int64_t> > cpp_dec_float_1000_64exp;

独自実装の多倍長浮動小数点数の特徴:

  • デフォルト値は0である
  • 基数は10。基数2ベースとは異なる振る舞いが可能
  • infinityNaNをサポートする。オーバーフローやゼロ割り時には、組み込みの浮動小数点数型と同じ振る舞いをする。
  • 全ての操作は、常に切り捨てを行う

GMPバックエンドの多倍長浮動小数点数

#include <boost/multiprecision/gmp.hpp>
説明
mpf_float_50 10進数の桁数が50の浮動小数点数型
mpf_float_100 10進数の桁数が100の浮動小数点数型
mpf_float_500 10進数の桁数が500の浮動小数点数型
mpf_float_1000 10進数の桁数が1,000の浮動小数点数型
mpf_float 可変制度で使用可能な浮動小数点数型

以下は、ユーザー定義の固定精度浮動小数点数型を定義する例である:

// 10進数の桁数が10,000の浮動小数点数型の定義
namespace mp = boost::multiprecision;
typedef mp::number<mp::gmp_float<10000> > mpf_dec_float_10000;

gmp_floatのテンプレート引数として0を指定すると、可変精度で表現可能になる。

GMP多倍長浮動小数点数の特徴:

  • デフォルト値は0である
  • GMPのグローバル設定を変更しない
  • GMPはinfinityNaNといった概念を持たないため、可能な限りオーバーフローやゼロ割りは避けること。オーバーフロー時またはゼロ割り時にはstd::overflow_error例外が送出される。

MPFRバックエンドの多倍長浮動小数点数

#include <boost/multiprecision/mpfr.hpp>

動的メモリ確保を行う多倍長浮動小数点数:

説明
mpfr_float_50 10進数の桁数が50の浮動小数点数型
mpfr_float_100 10進数の桁数が100の浮動小数点数型
mpfr_float_500 10進数の桁数が500の浮動小数点数型
mpfr_float_1000 10進数の桁数が1,000の浮動小数点数型
mpfr_float 可変制度で使用可能な浮動小数点数型

動的メモリ確保を行わない多倍長浮動小数点数

説明
static_mpfr_float_50 10進数の桁数が50の浮動小数点数型
static_mpfr_float_100 10進数の桁数が100の浮動小数点数型

以下は、ユーザー定義の、動的メモリ確保を行う固定精度浮動小数点数型を定義する例である:

// 10進数の桁数が10,000の浮動小数点数型の定義
namespace mp = boost::multiprecision;
typedef mp::number<mp::mpfr_float_backend<10000> > mpf_dec_float_10000;

mpfr_float_backendの第2テンプレート引数としてboost::multiprecision::allocate_stack列挙値を指定することで、動的メモリ確保を行わない多倍長浮動小数点数型の定義ができる。

MPFR多倍長浮動小数点数の特徴:

  • デフォルト値はNaNである
  • 全ての操作は、最近接値への丸めを使用する
  • GMPとMPFRのグローバル設定を変更しない
  • 0で割るとinfinityになる

文字列から多倍長浮動小数点数に変換するには、explicitな変換コンストラクタ、もしくはassign()メンバ関数を使用する。 文字列は、char配列およびstd::stringを受け取ることができる。

コンストラクタで文字列から変換

#include <iostream>
#include <string>
#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace boost::multiprecision;

int main()
{
    cpp_dec_float_100 x("3.14");                // char配列から変換
    cpp_dec_float_100 y(std::string("3.14"));   // std::stringから変換

    std::cout << x << std::endl;
    std::cout << y << std::endl;
}

出力:

3.14
3.14

assign()メンバ関数で文字列から変換

#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace boost::multiprecision;

int main()
{
    cpp_dec_float_100 x;
    x.assign("3.14");

    std::cout << x << std::endl;
}

出力:

3.14

変換できない文字列が渡された場合は、std::runtime_error例外が送出される。

文字列への変換には、str()メンバ関数を使用する。この関数は、std::string型で多倍長浮動小数点数の文字列表現を返す。

デフォルトでは固定小数点表記の文字列が返されるが、以下の引数を設定することで、精度と表記、その他出力方法を選択できる。

  • 第1引数: 出力する精度。0を指定した場合、できるだけ多くの桁数を出力する。
  • 第2引数: 出力フラグ。
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>

using boost::multiprecision::cpp_dec_float_50;

int main()
{
    cpp_dec_float_50 x = 3.14;

    // 固定小数点表記(デフォルト)
    {
        const std::string s = x.str();
        std::cout << s << std::endl;
    }
    // 固定小数点表記(明示的に指定)
    {
        const std::string s = x.str(0, std::ios_base::fixed);
        std::cout << s << std::endl;
    }
    // 科学的表記
    {
        const std::string s = x.str(0, std::ios_base::scientific);
        std::cout << s << std::endl;
    }
}

出力:

3.140000000000000124344978758017532527446746826171875
3.1400000000000001243449787580175325274467468261718750000000000000000000000
3.1400000000000001243449787580175325274467468261718750000000000000000000000e+00

Boost.Multiprecisionの多倍長浮動小数点数は、異なる精度間での変換をサポートしている。

小さい精度から大きい精度への変換

floatdouble型といった組み込みの浮動小数点数型から、cpp_dec_float_50cpp_dec_float_100といった多倍長浮動小数点数への暗黙変換が可能である。

また、cpp_dec_float_50からcpp_dec_float_100へ、といったより大きい精度への暗黙変換が可能である。

#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace boost::multiprecision;

int main()
{
    // floatからcpp_dec_float_50への暗黙変換
    float f = 3.14f;
    cpp_dec_float_50 f50 = f; // OK

    // cpp_dec_float_50からcpp_dec_float_100への暗黙変換
    cpp_dec_float_100 f100 = f50; // OK
}

大きい精度から小さい精度への変換

小さい精度への変換は、データが失われる可能性があるため、暗黙の型変換はサポートしない。

明示的な型変換を使用する場合のみ変換可能である。

#include <boost/multiprecision/cpp_dec_float.hpp>

using namespace boost::multiprecision;

int main()
{
    cpp_dec_float_100 f100 = 3.14;

//  cpp_dec_float_50 f50 = f100; // コンパイルエラー!変換できない
    cpp_dec_float_50 f50 = static_cast<cpp_dec_float_50>(f100); // OK
}

標準関数サポート

標準ライブラリで定義される以下の関数は、Boost.Multiprecisionの多倍長浮動小数点数でも使用できる。

これらの関数は、boost::multiprecision名前空間で定義される。他の関数は、公式ページを参照。なお、戻り値は式テンプレートなので、autoで受け取る際は、メンバ関数呼び出し時などに適宜static_castを行う必要がある場合がある。

関数 説明
T abs(T x);
T fabs(T x);
絶対値
T sqrt(T x); 平方根
T floor(T x); 床関数(引数より大きくない最近傍の整数)
T ceil(T x); 天井関数(引数より小さくない最近傍の整数)
T trunc(T x);
T itrunc(T x);
T ltrunc(T x);
T lltrunc(T x);
ゼロ方向への丸め
T round(T x);
T lround(T x);
T llround(T x);
四捨五入による丸め
T exp(T x); e (ネイピア数) を底とする指数関数
T log(T x); e (ネイピア数) を底とする自然対数
T log10(T x); 10 を底とする常用対数
T cos(T x); 余弦関数(コサイン)
T sin(T x); 正弦関数(サイン)
T tan(T x); 正接関数(タンジェント)
T acos(T x); 逆余弦関数(アークコサイン)
T asin(T x); 逆正弦関数(アークサイン)
T atan(T x); 逆正接関数(アークタンジェント)
T cosh(T x); 双曲線余弦関数(ハイパボリックコサイン)
T sinh(T x); 双曲線正弦関数(ハイパボリックサイン)
T tanh(T x); 双曲線正接関数(ハイパボリックタンジェント)
T ldexp(T x, int); 2 の冪乗との乗算
T frexp(T x, int*); 仮数部と 2 の冪乗への分解
T pow(T x, T y); 冪乗
T fmod(T x, T y); 浮動小数点剰余
T atan2(T x, T y); 対辺と隣辺からの逆正接関数(アークタンジェント)

documented boost version is 1.53.0