多倍長浮動小数点数を使用するには、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; |
a がb より小さいかの判定 |
a <= b; |
a がb 以下かの判定 |
a > b; |
a がb より大きいかの判定 |
a >= b; |
a がb 以上かの判定 |
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ベースとは異なる振る舞いが可能
infinity
とNaN
をサポートする。オーバーフローやゼロ割り時には、組み込みの浮動小数点数型と同じ振る舞いをする。- 全ての操作は、常に切り捨てを行う
#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は
infinity
やNaN
といった概念を持たないため、可能な限りオーバーフローやゼロ割りは避けること。オーバーフロー時またはゼロ割り時には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の多倍長浮動小数点数は、異なる精度間での変換をサポートしている。
小さい精度から大きい精度への変換
float
やdouble
型といった組み込みの浮動小数点数型から、cpp_dec_float_50
やcpp_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