Float — 多倍長浮動小数点

概要

Float は calx の任意精度浮動小数点型である。 内部表現は (符号, 仮数部 Int, 指数部 int64_t) の 3 つ組で、 値 $x$ を次のように表す。

$$x = (-1)^{s} \times m \times 2^{e}$$

ここで $s$ は符号ビット、$m$ は多倍長整数(Int)の仮数部、$e$ は 64 ビット整数の指数部である。

精度は 10 進桁数で指定し、内部ではビット精度に変換される。 IEEE 754 に準じた丸めモード(RoundingMode)をサポートし、 NaN および Infinity は全演算で安全に伝播する。

  • 任意精度 — 桁数に制限なし。数十万桁の計算が可能
  • NaN/Infinity 安全 — 特殊値は IEEE 754 と同様のセマンティクスで伝播
  • thread_local 定数キャッシュ — $\pi, e, \log 2$ 等の数学定数はスレッドごとにキャッシュされ、同一精度での再計算を回避
  • 精度追跡 — 有効ビット数(effectiveBits)と要求ビット数(requestedBits)を自動管理

コンストラクタ

シグネチャ説明
Float()デフォルト構築。値は 0
Float(int value)int から構築
Float(int64_t value)64 ビット整数から構築
Float(double value)double から構築(53 ビット精度)
Float(std::string_view str)文字列から構築(10 進)
Float(const Int& value)多倍長整数から構築(exact)
Float(const Int& mantissa, int64_t exponent, bool is_negative = false)仮数部 + 指数部から構築
Float(Int&& mantissa, int64_t exponent, bool is_negative = false)仮数部(ムーブ)+ 指数部から構築
Float(int64_t mantissa, int64_t exponent, bool is_negative = false)整数仮数部 + 指数部から構築

コピー・ムーブコンストラクタおよび代入演算子はすべて default で提供される。 int64_tdouble からの代入演算子も利用可能。

特殊値ファクトリ

すべて static メンバ関数である。

シグネチャ説明
Float positiveInfinity()$+\infty$ を返す
Float negativeInfinity()$-\infty$ を返す
Float nan()NaN を返す
Float epsilon(int precision)指定精度での機械イプシロン
Float zero(int precision)指定精度のゼロ
Float one(int precision)指定精度の 1

precision を省略すると defaultPrecision()(スレッドローカル)が使用される。

数学定数

すべて static メンバ関数で、thread_local キャッシュにより同一精度での再計算を回避する。

シグネチャ説明アルゴリズム
Float pi(int precision)円周率 $\pi \approx 3.1416$Chudnovsky (binary splitting)
Float e(int precision)自然対数の底 $e \approx 2.7183$$\sum 1/n!$ (binary splitting)
Float log2(int precision)$\ln 2 \approx 0.6931$atanh 系列
Float log10(int precision)$\ln 10 \approx 2.3026$atanh 系列
Float euler(int precision)Euler-Mascheroni 定数 $\gamma \approx 0.5772$Brent-McMillan
Float catalan(int precision)Catalan 定数 $G \approx 0.9160$Euler 級数

三角・円定数

シグネチャ説明
Float::half_pi(int precision)$\pi/2 \approx 1.5708$
Float::quarter_pi(int precision)$\pi/4 \approx 0.7854$
Float::two_pi(int precision)$2\pi \approx 6.2832$
Float::inv_pi(int precision)$1/\pi \approx 0.3183$
Float::two_inv_pi(int precision)$2/\pi \approx 0.6366$
Float::pi_squared_over_6(int precision)$\pi^2/6 = \zeta(2) \approx 1.6449$
Float::pi_squared_over_12(int precision)$\pi^2/12 \approx 0.8225$
Float::inv_sqrt_pi(int precision)$1/\sqrt{\pi} \approx 0.5642$
Float::two_inv_sqrt_pi(int precision)$2/\sqrt{\pi} \approx 1.1284$
Float::degree(int precision)$\pi/180 \approx 0.01745$

根号定数

シグネチャ説明
Float::sqrt2(int precision)$\sqrt{2} \approx 1.4142$
Float::sqrt3(int precision)$\sqrt{3} \approx 1.7321$
Float::sqrt5(int precision)$\sqrt{5} \approx 2.2361$
Float::inv_sqrt2(int precision)$1/\sqrt{2} \approx 0.7071$
Float::cbrt2(int precision)$\sqrt[3]{2} \approx 1.2599$

対数定数

シグネチャ説明
Float::ln3(int precision)$\ln 3 \approx 1.0986$
Float::ln5(int precision)$\ln 5 \approx 1.6094$
Float::log2e(int precision)$\log_2 e \approx 1.4427$
Float::log10e(int precision)$\log_{10} e \approx 0.4343$

著名な定数

シグネチャ説明
Float::phi(int precision)黄金比 $(1+\sqrt{5})/2 \approx 1.6180$
Float::lemniscate(int precision)レムニスケート定数 $\varpi \approx 2.6221$
Float::gamma14(int precision)$\Gamma(1/4) \approx 3.6256$
Float::zeta3(int precision)Apéry 定数 $\zeta(3) \approx 1.2021$
Float::zeta5(int precision)$\zeta(5) \approx 1.0369$
Float::zeta7(int precision)$\zeta(7) \approx 1.0083$
Float::glaisher(int precision)Glaisher-Kinkelin 定数 $A \approx 1.2824$
Float::khinchin(int precision)Khinchin 定数 $K \approx 2.6854$
Float::omega(int precision)$\Omega$ (Lambert $W(1)$) $\approx 0.5671$
Float::sin1(int precision)$\sin 1 \approx 0.8415$
Float::cos1(int precision)$\cos 1 \approx 0.5403$

希少な数学定数

シグネチャ説明
Float::plastic(int precision)プラスチック数 $\approx 1.3247$
Float::twin_prime(int precision)双子素数定数 $C_2 \approx 0.6602$
Float::landau_ramanujan(int precision)Landau-Ramanujan 定数 $\approx 0.7642$
Float::meissel_mertens(int precision)Meissel-Mertens 定数 $\approx 0.2615$
Float::bernstein(int precision)Bernstein 定数 $\approx 0.2801$
Float::gauss_kuzmin(int precision)Gauss-Kuzmin-Wirsing 定数 $\approx 0.3037$
Float::feigenbaum_delta(int precision)Feigenbaum $\delta \approx 4.6692$
Float::feigenbaum_alpha(int precision)Feigenbaum $\alpha \approx 2.5029$
Float::erdos_borwein(int precision)Erdős-Borwein 定数 $\approx 1.6066$
Float::laplace_limit(int precision)Laplace limit 定数 $\approx 0.6627$
Float::soldner(int precision)Ramanujan-Soldner 定数 $\mu \approx 1.4513$
Float::backhouse(int precision)Backhouse 定数 $\approx 1.4560$
Float::porter(int precision)Porter 定数 $\approx 1.4670$
Float::lieb_square_ice(int precision)Lieb の square ice 定数 $\approx 1.5396$
Float::niven(int precision)Niven 定数 $\approx 1.7052$
Float::reciprocal_fibonacci(int precision)逆 Fibonacci 定数 $\approx 3.3599$
Float::sierpinski(int precision)Sierpiński 定数 $\approx 2.5849$
Float::mills(int precision)Mills 定数 $\approx 1.3064$
Float::dottie(int precision)Dottie 数 $\approx 0.7391$
Float::golomb_dickman(int precision)Golomb-Dickman 定数 $\approx 0.6243$
Float::salem(int precision)Salem 定数 $\approx 1.1762$
Float::cahen(int precision)Cahen 定数 $\approx 0.6434$
Float::levy(int precision)Lévy 定数 $\approx 3.2758$
Float::copeland_erdos(int precision)Copeland-Erdős 定数 $\approx 0.2357$
Float::egamma_exp(int precision)$e^{\gamma} \approx 1.7811$

精度制御

シグネチャ説明
Float& setPrecision(int precision)有効桁数を設定(丸め処理あり)。自身への参照を返す
int precision() const現在の有効桁数を取得
int effectiveBits() const信頼できるビット数を取得
int requestedBits() const目標ビット数を取得
void truncateToApprox(int precision)ワード単位の高速近似切り詰め(中間計算用)
static int precisionToBits(int precision)10 進桁数 → ビット数
static int bitsToPrecision(int bits)ビット数 → 10 進桁数
static int defaultPrecision()スレッドローカルのデフォルト精度を取得
static void setDefaultPrecision(int precision)スレッドローカルのデフォルト精度を設定

丸めモード

enum class RoundingMode {
    ToNearest,      // 最も近い値に丸め(デフォルト)
    TowardZero,     // ゼロ方向に丸め(切り捨て)
    TowardPositive, // 正の無限大方向に丸め(切り上げ)
    TowardNegative, // 負の無限大方向に丸め(切り下げ)
    AwayFromZero    // ゼロから遠ざかる方向に丸め
};
シグネチャ説明
static RoundingMode roundingMode()現在の丸めモードを取得
static void setRoundingMode(RoundingMode mode)丸めモードを設定

状態確認

シグネチャ説明
bool isNaN() constNaN なら true
bool isInfinity() const$\pm\infty$ なら true
bool isZero() constゼロなら true
bool isNegative() const負なら true
bool isPositive() const非負なら true!isNegative()
bool isExact() const整数由来の正確な値なら true
bool isInteger() const整数値なら true(NaN/Infinity は false
bool fitsInt() constint 範囲に収まるか
bool fitsInt64() constint64_t 範囲に収まるか
bool fitsDouble() constdouble 範囲に収まるか

算術演算子

シグネチャ説明
Float operator+(const Float&, const Float&)加算
Float operator-(const Float&, const Float&)減算
Float operator*(const Float&, const Float&)乗算
Float operator/(const Float&, const Float&)除算
Float operator/(const Float&, int64_t)整数除算(高速パス)
Float& operator+=(const Float&)加算代入
Float& operator-=(const Float&)減算代入
Float& operator*=(const Float&)乗算代入
Float& operator/=(const Float&)除算代入
Float operator-(const Float&)単項マイナス(符号反転)
Float operator<<(const Float&, int)左シフト($\times 2^n$)
Float operator>>(const Float&, int)右シフト($\div 2^n$)

精度伝播ポリシー(デフォルト: MAX_PROPAGATION)に基づき、 結果の requestedBitsmax(lhs, rhs)effectiveBitsmin(lhs, rhs) となる。

比較演算子

シグネチャ説明
bool operator==(const Float&, const Float&)等価比較
std::partial_ordering operator<=>(const Float&, const Float&)三方比較(C++20)

三方比較演算子により !=, <, >, <=, >= が自動生成される。 NaN が含まれる比較はすべて std::partial_ordering::unordered を返す(IEEE 754 準拠)。

基本数学関数

すべて calx 名前空間のフリー関数である。 precision 引数は 10 進桁数で、計算の作業精度を指定する。 ムーブ版オーバーロードも提供されるが、表では省略する。

指数・対数

シグネチャ説明
Float exp(const Float& x, int precision)$e^x$
Float exp2(const Float& x, int precision)$2^x$
Float exp10(const Float& x, int precision)$10^x$
Float expm1(const Float& x, int precision)$e^x - 1$($x \approx 0$ で高精度)
Float log(const Float& x, int precision)$\ln x$(AGM 法)
Float log2(const Float& x, int precision)$\log_2 x$
Float log10(const Float& x, int precision)$\log_{10} x$
Float log1p(const Float& x, int precision)$\ln(1+x)$($x \approx 0$ で高精度)
Float logUi(unsigned long long n, int precision)整数の対数(素因数分解経由で高精度)

三角関数

シグネチャ説明
Float sin(const Float& x, int precision)$\sin x$
Float cos(const Float& x, int precision)$\cos x$
Float tan(const Float& x, int precision)$\tan x$
Float sinPi(const Float& x, int precision)$\sin(\pi x)$(整数点で正確に 0)
Float cosPi(const Float& x, int precision)$\cos(\pi x)$
Float tanPi(const Float& x, int precision)$\tan(\pi x)$
Float sec(const Float& x, int precision)$\sec x = 1/\cos x$
Float csc(const Float& x, int precision)$\csc x = 1/\sin x$
Float cot(const Float& x, int precision)$\cot x = \cos x/\sin x$

逆三角関数

シグネチャ説明
Float asin(const Float& x, int precision)$\arcsin x$
Float acos(const Float& x, int precision)$\arccos x$
Float atan(const Float& x, int precision)$\arctan x$(Taylor + 引数半減)
Float atan2(const Float& y, const Float& x, int precision)$\mathrm{atan2}(y, x)$
Float asinPi(const Float& x, int precision)$\arcsin(x) / \pi$
Float acosPi(const Float& x, int precision)$\arccos(x) / \pi$
Float atanPi(const Float& x, int precision)$\arctan(x) / \pi$

双曲線関数

シグネチャ説明
Float sinh(const Float& x, int precision)$\sinh x$
Float cosh(const Float& x, int precision)$\cosh x$
Float tanh(const Float& x, int precision)$\tanh x$
Float sech(const Float& x, int precision)$\mathrm{sech}\,x = 1/\cosh x$
Float csch(const Float& x, int precision)$\mathrm{csch}\,x = 1/\sinh x$
Float coth(const Float& x, int precision)$\coth x = \cosh x/\sinh x$

逆双曲線関数

シグネチャ説明
Float asinh(const Float& x, int precision)$\mathrm{arcsinh}\,x$
Float acosh(const Float& x, int precision)$\mathrm{arccosh}\,x$
Float atanh(const Float& x, int precision)$\mathrm{arctanh}\,x$

冪乗・根

シグネチャ説明
Float sqr(const Float& x, int precision)$x^2$(二乗、最適化アルゴリズム使用)
Float pow(const Float& x, const Float& y, int precision)$x^y$
Float pow(const Float& x, int n, int precision)$x^n$(整数冪、二分累乗法)
Float sqrt(const Float& x, int precision)$\sqrt{x}$
Float cbrt(const Float& x, int precision)$\sqrt[3]{x}$
Float nthRoot(const Float& x, int n, int precision)$\sqrt[n]{x}$
Float recSqrt(const Float& x, int precision)$1/\sqrt{x}$(逆平方根)
Float hypot(const Float& x, const Float& y, int precision)$\sqrt{x^2 + y^2}$(オーバーフロー安全)

その他

シグネチャ説明
Float abs(const Float& x)$|x|$
Float fma(const Float& a, const Float& b, const Float& c, int precision)$ab + c$(融合積和)
Float fms(const Float& a, const Float& b, const Float& c, int precision)$ab - c$(融合積差)
Float fmma(const Float& a, const Float& b, const Float& c, const Float& d, int precision)$ab + cd$(二重融合積和)
Float fmms(const Float& a, const Float& b, const Float& c, const Float& d, int precision)$ab - cd$(二重融合積差)
Float factorial(int n, int precision)$n!$
void sinCos(const Float& x, Float& s, Float& c, int precision)$\sin x$ と $\cos x$ を同時計算
void sinhCosh(const Float& x, Float& s, Float& c, int precision)$\sinh x$ と $\cosh x$ を同時計算
Float agm(const Float& a, const Float& b, int precision)算術幾何平均 $\mathrm{AGM}(a, b)$
Float sum(std::span<const Float> values, int precision)高精度総和
Float dot(std::span<const Float> a, std::span<const Float> b, int precision)高精度内積

誤差関数・ガンマ関数

シグネチャ説明
Float erf(const Float& x, int precision)誤差関数 $\mathrm{erf}(x)$
Float erfc(const Float& x, int precision)相補誤差関数 $\mathrm{erfc}(x) = 1 - \mathrm{erf}(x)$
Float erfcx(const Float& x, int precision)スケール付き相補誤差関数 $e^{x^2}\,\mathrm{erfc}(x)$
Float gamma(const Float& x, int precision)$\Gamma(x)$
Float lnGamma(const Float& x, int precision)$\ln\Gamma(x)$
Float beta(const Float& a, const Float& b, int precision)$B(a, b) = \Gamma(a)\Gamma(b)/\Gamma(a+b)$
Float digamma(const Float& x, int precision)$\psi(x) = \Gamma'(x)/\Gamma(x)$
Float trigamma(const Float& x, int precision)$\psi'(x)$
Float polygamma(int n, const Float& x, int precision)$\psi^{(n)}(x)$
Float gammaP(const Float& a, const Float& x, int precision)正規化下側不完全ガンマ $P(a,x)$
Float gammaQ(const Float& a, const Float& x, int precision)正規化上側不完全ガンマ $Q(a,x)$
Float gammaLower(const Float& a, const Float& x, int precision)下側不完全ガンマ $\gamma(a,x)$
Float gammaUpper(const Float& a, const Float& x, int precision)上側不完全ガンマ $\Gamma(a,x)$

丸め・整数部

すべて calx 名前空間のフリー関数。ムーブ版オーバーロードも提供される。

シグネチャ説明
Float floor(const Float& x)$\lfloor x \rfloor$(床関数)
Float ceil(const Float& x)$\lceil x \rceil$(天井関数)
Float round(const Float& x)最近接丸め(half-away-from-zero: tie で 0 から遠い側)
Float roundEven(const Float& x)最近接偶数丸め(banker's rounding: tie で偶数側)
Float trunc(const Float& x)ゼロ方向への切り捨て
Float frac(const Float& x)小数部 $x - \lfloor x \rfloor$
Float nearbyint(const Float& x)round と同等
Float rint(const Float& x)round と同等
Float modf(const Float& x, Float& iptr)整数部を iptr に、小数部を返す
Float fmod(const Float& x, const Float& y)浮動小数点剰余 $x - \mathrm{trunc}(x/y) \cdot y$
Float remainder(const Float& x, const Float& y)IEEE 754 剰余 $x - \mathrm{roundEven}(x/y) \cdot y$
std::pair<Float, int> remquo(const Float& x, const Float& y)remainder + 商の符号付き下位 3 ビット
Float ldexp(const Float& x, int exp)$x \times 2^{\mathrm{exp}}$
Float frexp(const Float& x, int* exp)仮数部 $[0.5, 1)$ と指数を分離
Float scalbn(const Float& x, int n)ldexp と同等
int64_t ilogb(const Float& x)$\lfloor \log_2 |x| \rfloor$
Float logb(const Float& x)$\lfloor \log_2 |x| \rfloor$(Float 型で返す)

ユーティリティ

シグネチャ説明
Float fmin(const Float& a, const Float& b)NaN を無視した最小値
Float fmax(const Float& a, const Float& b)NaN を無視した最大値
Float fdim(const Float& a, const Float& b)$\max(a - b, 0)$
Float copySign(const Float& x, const Float& y)$y$ の符号を $x$ にコピー
bool signBit(const Float& x)負なら true
Float nextAbove(const Float& x)$x$ より大きい最小の表現可能値
Float nextBelow(const Float& x)$x$ より小さい最大の表現可能値
Float lerp(const Float& a, const Float& b, const Float& t, int precision)線形補間 $a + t(b - a)$
Float midpoint(const Float& a, const Float& b)中点 $(a + b) / 2$
void swap(Float& a, Float& b) noexceptスワップ

文字列変換

シグネチャ説明
std::string toString(int precision = -1) const10 進科学表記 (3.14e+0)
std::string toString(int base, int fracDigits) constN 進数表示 (2〜36 進)。toString(2, 8)"11.01010101"toString(16, 4)"3.243f"
std::string toDecimalString(int precision = -1) const10 進固定小数点表記
std::string toScientificString(int precision = -1) const科学表記 ($1.23 \times 10^4$ 形式)
double toDouble() constdouble に変換(精度損失の可能性あり)
Int toInt() constInt に変換(小数部切り捨て)
ostream& operator<<(ostream&, const Float&)ストリーム出力
istream& operator>>(istream&, Float&)ストリーム入力

内部アクセス

シグネチャ説明
const Int& mantissa() const仮数部(多倍長整数)への参照
int64_t exponent() const指数部(2 進指数)
bool isNegative() const符号フラグ
int bitLength() const仮数部のビット長

使用例

Pi の計算

#include <math/core/mp/Float.hpp>
using namespace calx;

// 1000 桁の円周率を計算(Chudnovsky アルゴリズム)
Float::setDefaultPrecision(1000);
Float pi = Float::pi(1000);
std::cout << pi.toDecimalString(1000) << std::endl;
// 3.14159265358979323846264338327950288419716939937510...

exp / log の多倍長演算

#include <math/core/mp/Float.hpp>
using namespace calx;

int prec = 30;
Float::setDefaultPrecision(prec);
Float x("1.5");

Float ex = exp(x, prec);       // e^1.5
Float lx = log(ex, prec);      // ln(e^1.5) = 1.5
std::cout << "exp(1.5) = " << ex.toDecimalString(prec) << std::endl;
std::cout << "log(exp(1.5)) = " << lx.toDecimalString(prec) << std::endl;
// 30 桁精度で完全に 1.5 に一致

NaN / Infinity の安全な伝播

Float inf = Float::positiveInfinity();
Float nan = Float::nan();
Float z   = Float::zero();

Float r1 = inf + Float(1);     // +Inf
Float r2 = inf - inf;          // NaN
Float r3 = nan + Float(42);   // NaN
Float r4 = Float(1) / z;      // +Inf

std::cout << r1.isInfinity()  // true
          << r2.isNaN()       // true
          << r3.isNaN()       // true
          << r4.isInfinity(); // true

精度制御と定数キャッシュ

// thread_local キャッシュにより、同一精度での再呼び出しは高速
Float pi1 = Float::pi(500);   // 初回: 計算
Float pi2 = Float::pi(500);   // 2 回目: キャッシュから即時返却
Float pi3 = Float::pi(1000);  // 精度が異なるため再計算

// 丸めモードの変更
Float::setRoundingMode(RoundingMode::TowardZero);
Float x("1.999");
x.setPrecision(3);  // TowardZero で丸め