ホームページ >バックエンド開発 >Golang >プログラミング言語間のビッグ十進演算: ギャップを埋める

プログラミング言語間のビッグ十進演算: ギャップを埋める

Barbara Streisand
Barbara Streisandオリジナル
2024-12-27 12:33:11802ブラウズ

Big Decimal Arithmetic Across Programming Languages: Bridging the Gap

金融、暗号化、科学技術計算などの分野では、高精度の演算を処理することが不可欠です。一部のプログラミング言語は任意精度の算術演算に対する堅牢なネイティブ サポートを提供しますが、他のプログラミング言語では同様の機能を実現するために回避策またはサードパーティの統合が必要です。この記事では、言語間でのビッグ 10 進数サポートの状況を調査し、この機能が欠けている言語の解決策について説明します。


サポートが組み込まれている言語

パイソン

  • Python は、任意精度の 10 進数演算を可能にする decimal.Decimal モジュールを提供します。これは、ユーザー定義の精度と丸めルールに準拠した財務計算に特に適しています。
  • mpmath のようなライブラリは、Python の機能を拡張して、高度な数学関数の任意精度の浮動小数点演算をサポートします。

ジャワ

  • Java の標準ライブラリには、任意精度の 10 進数を処理するための高性能ツールである BigDecimal クラスが含まれています。すべての標準演算 (加算、減算、乗算、除算、平方根など) をサポートしており、金融アプリケーションで広く使用されています。

C

  • C は、Boost Multiprecision などのライブラリを提供します。これには、任意精度の 10 進演算用の cpp_dec_float および mp_float が含まれます。
  • MPFRGMP は、非常に高精度の演算のために C で使用することもでき、乗算、除算などの最適化されたアルゴリズムを提供します。

C (GMP/MPFR)

  • GNU MP (GMP) ライブラリは、任意精度の算術演算のゴールドスタンダードです。パフォーマンスが重要なアプリケーション向けに、高度なアルゴリズム (Karatsuba、Toom-Cook、FFT、Barrett リダクションなど) の高度に最適化された実装を提供します。
  • GMP 上に構築された MPFR も、高精度浮動小数点演算に特化した強力なライブラリです。

サポートが制限されている言語

多くの最新のプログラミング言語 (Go、Node.js、Elixir など) は、ビッグ 10 進演算をネイティブにサポートしていないため、高精度を必要とするアプリケーションでは課題が生じる可能性があります。

行きます

  • Go には、任意精度の整数と有理数用の math/big パッケージが含まれていますが、Java の BigDecimal のような固定小数点小数点のネイティブ サポートがありません。 shopspring/decimal や Cockroachdb/apd などのサードパーティ ライブラリはギャップを埋めるのに役立ちますが、GMP や Java の BigDecimal に比べて機能が豊富ではありません。

Node.js (JavaScript)

  • JavaScript は IEEE 754 倍精度浮動小数点数に依存しているため、精度が制限されています。 decmal.js や big.js などのライブラリは、任意精度の算術演算をエミュレートしますが、Python や Java のネイティブ実装ほど高速ではありません。

エリクサー

  • Elixir にはネイティブのビッグ 10 進数演算は含まれていませんが、金融および正確な 10 進数計算用に特別に構築された Decimal のようなライブラリが提供されています。ただし、これらのライブラリには、GMP にある高度な最適化がありません。

限定的なサポートの回避策

1.外部関数インターフェイス (FFI) の統合

Go、Node.js、Elixir などの言語は、FFI を使用して高性能ライブラリ (GMP、MPFR など) と統合できます。これにより高度なアルゴリズムにアクセスできるようになりますが、言語間の呼び出しにより複雑さが増し、パフォーマンスのオーバーヘッドが発生する可能性があります。

2. gRPC または Thrift 経由のリモート サービス

別のアプローチは、堅牢なビッグ 10 進数をサポートする言語 (例: Python、Java、GMP を使用した C) でマイクロサービスを作成し、それを gRPC または Thrift 経由で公開することです。 。プライマリ アプリケーション (Go、Node.js、Elixir など) は、高精度の計算のためにこのサービスへの RPC 呼び出しを行うことができます。

リモートサービスの利点
  • 一元化された実装により、正確性と一貫性が保証されます。
  • すべてのアプリケーションに FFI を組み込む場合と比較して、保守と拡張が容易です。
デメリット
  • ネットワークのオーバーヘッドにより遅延が増加します。
  • サービスの保守と監視が複雑になります。

実際の使用例: 財務計算

フィンテック アプリケーションが Node.js または Go で記述されているが、次のような高精度の操作が必要であるとします。

  • 数百の期間にわたる複利を計算します。
  • 小数点以下の為替レートで通貨を変換します。
  • 厳密な四捨五入ルールを使用して税計算を実行します。

ビッグ 10 進数のサポートを再実装する代わりに、アプリケーションでは次のことが可能です。

  1. バックエンド計算に gRPC を使用して Python または Java を統合します。
  2. C マイクロサービスで GMP またはブースト多重精度を使用します。
  3. これらのサービスにアクセスするための REST または Thrift ベースの API を提供します。

Big Decimal 演算のアルゴリズム

GMP や MPFR などの高精度算術ライブラリは、乗算、除算、剰余算術などの演算に高度なアルゴリズムを採用しています。これらのアルゴリズムは、多数のパフォーマンスとスケーラビリティを考慮して最適化されています。

1.乗算アルゴリズム

  • 古典的な乗算: 小さい数値に使用されます。 としてスケールします (O(n2))(O(n^2)) (O(n2)) 時間の複雑さの点で。
  • Karatsuba Algorithm: を備えた分割統治アルゴリズム。 (O( n1.58))(O(n^{1.5 8}))(O(n1.58)) 複雑さ。中程度の数値に使用されます。
  • Toom-Cook (Toom-3): より大きな入力のためにカラツバを一般化します。としてスケールします (O(nログ 3(5)))(O(n^{log_3(5)}))(O(nログ3( 5))) .
  • FFT ベースの乗算: 非常に大きな数値に対して高速フーリエ変換を使用します。 (O(n ログn))(O(n log n))(O(nlogn)) 複雑さ。

2.除算と剰余演算

  • ニュートン・ラフソン法: 反復改良による高速除算に使用されます。
  • Barrett Reduction: 逆数を事前計算することにより、特に大きなオペランドのモジュラー演算を最適化します。
  • Montgomery Reduction: 暗号アプリケーションにおける剰余乗算に効率的です。

3.べき乗

  • 二乗による累乗: 整数のべき乗に一般的で、 (O(lo) gn))(O(log n))(O(logn)) 複雑さ。
  • 浮動小数点累乗: 10 進の底と指数にテイラー級数または対数/指数変換を使用します。

4.平方根と対数

  • ニュートン法: 平方根近似に一般的です。
  • Taylor/Maclaurin シリーズ: 高精度の対数計算に使用されます。

Go、Elixir、Node.js に欠けているアルゴリズム

  1. 高度な乗算の欠如:

    • Go の math/big は、小さな整数には古典的な乗算を使用し、大きな整数にはカラツバを使用しますが、非常に大きな入力には Toom-Cook または FFT を使用しません。
    • Elixir と Node.js はサードパーティのライブラリに依存していますが、多くの場合、FFT などの高度な技術が欠けています。
  2. 限定的な分割の最適化:

    • GMP または MPFR がなければ、Go、Elixir、および Node.js のほとんどの実装には Barrett または Montgomery 削減が欠けており、より遅い反復メソッドに依存します。
  3. 対数/指数関数のネイティブ サポートはありません:

    • Python の mpmath や Java の BigDecimal などのライブラリはこれらを提供しますが、Go、Elixir、Node.js には高度な数学のためのネイティブの Big Decimal サポートがありません。

高精度アルゴリズムの実装における課題

  1. パフォーマンス

    • FFT 乗算などのアルゴリズムを実装するには、数値の安定性とキャッシュの局所性の最適化についての深い理解が必要です。
    • 速度と精度のバランスを取るのは困難です。単純な実装は、GMP のような最適化された実装よりも桁違いに遅くなる可能性があります。
  2. 精密な取り扱い

    • 除算や対数などの演算の正確性を確保するには、四捨五入や誤差伝播の処理を慎重に行う必要があります。
    • モジュラー演算 (バレット削減など) で精度スケーリングを実装すると、複雑さが増します。
  3. 同時実行性

    • Go や Elixir などの言語は同時システム向けに設計されていますが、高精度の演算は本質的に逐次的であるため、ボトルネックを回避するには慎重な最適化が必要です。
  4. メモリ管理

    • 任意精度の演算には動的に割り当てられたメモリが必要であり、Go や Node.js などのガベージ コレクション言語での実装が複雑になります。

測定用のベンチマーク データセット

  1. 算術精度テスト

    • 次のような操作を検証します (0.1 0.2=0.3)(0.1 0.2 = 0.3)(0.1 0.2=0.3) 分数演算を正しく処理できるようにするため。
    • エッジケースをテストします。例: (10100÷1099=10)( 10^{100} div 10^{99} = 10)(10100÷1099=10) .
  2. パフォーマンス ベンチマーク

    • さまざまなサイズの数値を持つデータセットを使用します。例: (10 10)(10^{10})(1010) (10100)(10^{100})(10100) 、 そして (101000)(10^{1000}) (101000) 、スケーラビリティをテストします。
    • ランタイムとメモリ使用量を GMP などのライブラリと比較します。
  3. 現実世界の金融データ

    • 数千の期間にわたる高精度の複利計算を実行します。
    • 厳密な四捨五入ルールを使用して通貨換算と税金計算を検証します。
  4. 数学の専門テスト

    • コンピューティング (π)(π)(π) または (2)(sqrt{2})(2) 小数点以下何百万桁まで。
    • mpmath などの既知のライブラリを参照として使用して、超越数でベンチマークを実行します。

これらの言語に不足している機能を統合する方法

  1. GMP などのライブラリに FFI を使用する

    • Go や Node.js などの言語は FFI 経由で GMP を統合できますが、これにより言語間の呼び出しによるパフォーマンスのオーバーヘッドが生じます。
  2. リモート サービスを構築する

    • gRPC または Thrift を使用して、Python、Java、または C で高精度のサービスを作成します。
    • サービスがすべての必要な操作 (加算、乗算、平方根など) に対応する API を提供していることを確認します。
  3. サードパーティ ライブラリ

    • 開始点として、コミュニティでサポートされているライブラリ (Go の shopspring/Decimal および Cockroachdb/apd、Node.js の decmal.js など) を使用します。

PHP での Big Decimal のサポート

ネイティブサポート

PHP には、標準ライブラリにネイティブの 10 進数の算術演算が含まれていません。高精度の整数および 10 進数の算術演算のために、bcmath (Binary Calculator) 拡張機能または gmp 拡張機能に依存しています。

  1. BCMath:
    • 任意精度の演算用に設計されています。
    • 基本的な演算 (加算、減算、乗算、除算、剰余、べき乗) をサポートします。
    • 平方根、対数、三角演算などの高度な関数はサポートされていません。
  2. GMP:
    • 整数に対して任意精度の算術演算を提供しますが、小数に対するサポートは制限されています。

サードパーティのライブラリ

  • BrickMath: PHP での任意精度の算術演算用の最新ライブラリであり、小数と整数をサポートしています。
  • php-decimal: Python の 10 進数モジュールや Ruby の BigDecimal に似た高精度 10 進数演算を実装します。

課題

  • パフォーマンス:
    • PHP の bcmath は、GMP や C の Boost Multiprecision に比べて遅いです。
    • 非常に大きな数値または高精度の数値を処理すると、パフォーマンスのボトルネックが発生する可能性があります。
  • 限定された高度な機能:
    • ほとんどの PHP ライブラリは、FFT や Karatsuba などの高度なアルゴリズムを提供せず、基本的な実装に依存しています。

結論

Python、Java、C などの言語は、成熟したライブラリによる任意精度の演算のサポートに優れています。ただし、Go、Node.js、Elixir などの言語の場合、FFI を介して外部ライブラリを統合するか、RPC ベースのサービスを利用することが実用的なソリューションです。これらのアプローチにより、これらの言語のアプリケーションは、ネイティブ ライブラリに制限されることなく、金融や科学研究などの分野に必要な高い精度と正確性を確実に満たすことができます。

複数の言語の長所を組み合わせることで、開発者は効率的で正確な信頼性の高いシステムを構築できます。


ここでは、CMakeGMPMPFR ライブラリ を使用して C プロジェクト を作成するためのステップバイステップのガイドを示します。


1.フォルダー構造

gmp-mpfr-project/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
└── build/ (Generated by CMake)

2.CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(GMP_MPFR_Example)

# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find GMP library
find_package(GMP REQUIRED)
find_package(MPFR REQUIRED)

# Include directories for GMP and MPFR
include_directories(${GMP_INCLUDE_DIR} ${MPFR_INCLUDE_DIR})

# Add executable
add_executable(gmp_mpfr_example src/main.cpp)

# Link libraries
target_link_libraries(gmp_mpfr_example PRIVATE ${GMP_LIBRARIES} ${MPFR_LIBRARIES})

3.src/main.cpp

GMP ライブラリと MPFR ライブラリの基本的な使用法を示す簡単な例。

#include <iostream>
#include <gmp.h>
#include <mpfr.h>

int main() {
    // GMP example: Factorial computation
    mpz_t factorial;
    mpz_init(factorial);
    mpz_fac_ui(factorial, 20); // Compute 20!
    std::cout << "20! = " << mpz_get_str(nullptr, 10, factorial) << std::endl;
    mpz_clear(factorial);

    // MPFR example: High-precision computation
    mpfr_t pi;
    mpfr_init2(pi, 256); // 256-bit precision
    mpfr_const_pi(pi, MPFR_RNDN); // Compute pi
    std::cout << "Pi = ";
    mpfr_out_str(stdout, 10, 0, pi, MPFR_RNDN);
    std::cout << std::endl;
    mpfr_clear(pi);

    return 0;
}

4. ビルドと実行の手順

a.ライブラリのインストール

GMP ライブラリと MPFR ライブラリがインストールされていることを確認します。 Linux の場合:

sudo apt update
sudo apt install libgmp-dev libmpfr-dev

b. CMake を使用した構成とビルド

cd gmp-mpfr-project
mkdir build
cd build
cmake ..
make

c.例を実行する

./gmp_mpfr_example

出力

20! = 2432902008176640000
Pi = 3.1415926535897932384626433832795028841971693993751

以上がプログラミング言語間のビッグ十進演算: ギャップを埋めるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。