Boost.Multiprecision で桁あふれしない階乗と円周率 1 万桁

Boost 1.53.0 では、多倍長精度の整数、有理数浮動小数点数を扱う Multiprecision ライブラリが追加されました。
どの数値型も基本的な演算子に対応し、浮動小数点数は Boost.Math を含む pow や sin などの数学関数に対応しています。

整数型は、コンパイル時に精度が固定された int128_t 型や int256_t 型などのほか、メモリが許す限り実行時にどこまでも精度を拡張できる cpp_int 型が用意されています。
cpp_int 型を使って、桁あふれしない階乗関数を書いてみましょう。

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

using namespace boost::multiprecision;

cpp_int Factorial( unsigned n )
{
	cpp_int x = 1;

	while(n)
	{
		x *= n--;
	}

	return x;
}

int main()
{
	std::cout << Factorial(3) << '\n';

	std::cout << Factorial(100) << '\n';

	std::cout << Factorial(300) << '\n';
}
6
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
306057512216440636035370461297268629388588804173576999416776741259476533176716867465515291422477573349939147888701726368864263907759003154226842927906974559841225476930271954604008012215776252176854255965356903506788725264321896264299365204576448830388909753943489625436053225980776521270822437639449120128678675368305712293681943649956460498166450227716500185176546469340112226034729724066333258583506870150169794168850353752137554910289126407157154830282284937952636580145235233156936482233436799254594095276820608062232812387383880817049600000000000000000000000000000000000000000000000000000000000000000000000000


浮動小数点数型はコンパイル時に精度(桁数)を指定します。
50 桁の cpp_dec_float_50, 100 桁の cpp_dec_float_100 型があらかじめ用意されています。
2 の平方根を 100 桁、Boost.Math の constants::pi を使って円周率を 1 万桁表示してみましょう。

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

using namespace boost::multiprecision;
using namespace boost::math::constants;

int main()
{
	const cpp_dec_float_100 f = 2.0;

	std::cout << std::setprecision(101)
			  << sqrt(f)
			  << '\n';

	std::cout << std::setprecision(10001)
			  << pi<number<cpp_dec_float<10000>>>()
			  << '\n';
}
1.4142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727
3.14159265358979323846264338327950288419716939937510582097494459230781640628620...05600101655256375679

ドキュメント によると
The actual precision of a cpp_dec_float is always slightly higher than the number of digits specified in the template parameter, actually how much higher is an implementation detail but is always at least 8 decimal digits.
と、実際には cpp_dec_float は指定した桁数より少し大きい精度を持っていますが、心配な場合は必要な分より大きい精度を指定しておくといいでしょう。

cpp_dec_float の桁数は、内部計算で桁落ちが発生しないよう 14368 が最大値となっていて、それを超えるとコンパイルエラーが発生します。 (boost 1.53.0)