C++ での Boost ライブラリの使い方
この記事では、C++ で Boost ライブラリを利用する方法を説明します。
Boost MultiprecisionLibrary を使用して高精度の計算を実行する
Boost は、C++ ライブラリのオープンソースライセンスコレクションであり、汎用プログラミングから、画像処理や分散メモリ並列処理などのドメイン固有ライブラリまで、さまざまなツールを提供します。数十の個別のライブラリが含まれており、そのうちのいくつかは最近の STL バージョンに組み込まれています。
これらのライブラリは広範囲にわたってピアレビューされており、オープンソースまたは商用プロジェクト向けに高品質で信頼性の高いコードを提供します。
Boost ライブラリについては膨大な量の資料を取り上げる必要があるため、これらのライブラリがいかに強力であるかの例をいくつか紹介します。Boost ライブラリは通常、ほとんどのオペレーティングシステムに含まれておらず、過去にインストールしたことがない場合は、インストールする必要がある可能性が高いことに注意してください。
まず、高精度の数学的計算を処理する機能を備えた Multiprecision
ライブラリから始めます。一般に、数値の C++ 基本型には、最大 64 ビット値の制限されたサイズがあることがわかっています。浮動小数点数を無視しても、組み込み型で表現できる大きな整数は、unsigned
の値で最大で約 1,84 * 10^19
になります。これは、多くの実際のアプリケーションにとって、または便利な高精度の電卓アプリを実装したいプログラマーにとってさえ問題になる可能性があります。
Multiprecision
ライブラリは、int128_t
、int256_t
、int512_t
、int1024_t
などのさまざまな定義済みタイプの整数型を提供します。これらは、固定サイズの整数値を格納するために使用できます。一方、ユーザーが事前に計算の限界を知らない場合は、cpp_int
型を使用して任意精度の整数を格納できます。
これらの型の基本的な使用法を次のコードスニペットに示します。これは、long long
型で表される最大数の乗算を示しています。
#include <boost/multiprecision/cpp_int.hpp>
using std::cout;
using std::endl;
using namespace boost::multiprecision;
int128_t Multiply(long long A, long long B) {
int128_t ans = (int128_t)A * B;
return ans;
}
cpp_int Multiply2(long long A, long long B) {
cpp_int ans = (cpp_int)A * B;
return ans;
}
int main() {
long long first = 9223372036854775807;
long long second = 9223372036854775807;
cout << "Product of " << first << " * " << second << " = \n"
<< Multiply(first, second) << endl;
cout << "Product of " << first << " * " << second << " = \n"
<< Multiply2(first, second) << endl;
return EXIT_SUCCESS;
}
出力:
Product of 9223372036854775807 * 9223372036854775807 =
85070591730234615847396907784232501249
Product of 9223372036854775807 * 9223372036854775807 =
85070591730234615847396907784232501249
Boost の循環バッファデータ構造を STL 準拠のコンテナとして使う
Boost ライブラリが提供するもう 1つの強力なツールは、STL 準拠のコンテナとして実装された循環バッファデータ構造です。循環バッファは、std::list
および std::deque
に似ていますが、容量が固定されており、オブジェクトの構築時に対応するメモリが割り当てられる点が異なります。
ユーザーは、<boost/circular_buffer.hpp>
ヘッダーを含め、boost::circular_buffer
名で新しいオブジェクトを作成する必要があります。後者はテンプレートクラスであり、バッファに格納される要素の型名を受け入れることに注意してください。データ構造は、バッファのそれぞれの端に要素を追加するための push_back
/push_front
メンバー関数と、要素を削除するための pop_back
/pop_front
関数も提供します。
循環バッファがいっぱいになると、新しく追加された要素はバッファの開始から上書きされます。次のコード例は、boost::circular_buffer
の一般的な操作を示していますが、クラスの詳細な説明はここにあります。
#include <boost/circular_buffer.hpp>
#include <boost/multiprecision/cpp_int.hpp>
using std::cout;
using std::endl;
template <typename T>
void printBuffer(boost::circular_buffer<T> cbuf) {
for (const auto &item : cbuf) {
cout << item << "; ";
}
cout << endl;
}
int main() {
boost::circular_buffer<int> cb(10);
for (int i = 0; i < 10; ++i) {
cb.push_back(i);
}
printBuffer(cb);
cout << "cb.back: " << cb.back() << endl;
cout << "cb.front: " << cb.front() << endl;
for (int i = 0; i < 5; ++i) {
cb.push_front(i);
}
printBuffer(cb);
cout << "cb.back: " << cb.back() << endl;
cout << "cb.front: " << cb.front() << endl;
cb.pop_back();
printBuffer(cb);
cb.pop_front();
printBuffer(cb);
return EXIT_SUCCESS;
}
出力:
0; 1; 2; 3; 4; 5; 6; 7; 8; 9;
cb.back: 9
cb.front: 0
4; 3; 2; 1; 0; 0; 1; 2; 3; 4;
cb.back: 4
cb.front: 4
4; 3; 2; 1; 0; 0; 1; 2; 3;
3; 2; 1; 0; 0; 1; 2; 3;