web-dev-qa-db-ja.com

C ++での128ビット数の表現

C++で128ビットの数値を表す最良の方法は何ですか?可能な限り組み込みの数値型に近い動作をする必要があります(つまり、すべての算術演算子などをサポートします)。

2 64ビットまたは4 32ビットの数を持つクラスを構築することを考えていました。または、128ビットブロックのメモリを作成して、すべてを自分で行うこともできます。

もっと簡単な/より標準的な方法がありますか、それとも自分で実装するときにめちゃくちゃにしない可能性がありますか? :)

また、256ビット、512ビットなどに拡張できればいいでしょう。

55
David Coufal

開発された他のライブラリを調べてください。多くの人があなたの前にこれをやりたいと思っています。 :D

bigint C++ を試してください

13

EDIT:最初にこれを書いたとき boost::multiprecision::uint128_t はまだありませんでした。歴史的な理由でこの回答を保持します。


以前にuint128クラスを作成しました。次のURLで確認できます: http://www.codef00.com/code/uint128.h

数学演算子のすべてのバリアントを自動的に提供するためにブーストに依存しているため、ネイティブunsigned intタイプ。

次のような文字列で初期化するなど、組み込み型にはいくつかのマイナーな拡張機能があります。

uint128_t x("12345678901234567890");

次のように使用できるC99のマクロと同様に機能する便利なマクロがあります。

uint128_t x = U128_C(12345678901234567890);
65
Evan Teran

これは、特殊なケースです。特に、探しているプラ​​ットフォームを指定しなかったためですが、GCCでは、mode(TI)と呼ばれるものを使用して、(合成された)128ビット操作を取得できます。インスタンス:

   typedef unsigned int uint128_t __attribute__((mode(TI)));

   uint64_t x = 0xABCDEF01234568;
   uint64_t y = ~x;

   uint128_t result = ((uint128_t) x * y);

   printf("%016llX * %016llX -> ", x, y);

   uint64_t r1 = (result >> 64);
   uint64_t r2 = result;

   printf("%016llX %016llX\n", r1, r2);

ただし、これは64ビットプロセッサでのみ機能します。

いずれにせよ、あなたはこれを解決するために多精度の算術演算を見ています。 mode(TI)を指定すると、コンパイラが操作を自動的に生成します。そうでない場合は、明示的に記述する必要があります。

一般的なbigintパッケージを使用できます。私が知っているC++のものには、数論パッケージ LiDIA および [〜#〜] ntl [〜#〜] が含まれ、暗号化コードに使用されるbigintパッケージが含まれています- Crypto ++ および Botan )。さらに、 GnuMP があります。これは、標準のC MPIライブラリです(そして、C++ラッパーもありますが、前回見たときはあまり文書化されていなかったようです)これらはすべて高速になるように設計されていますが、おそらくより大きな(1000+ビット)数に合わせて調整されているため、128ビットでは多くのオーバーヘッドを処理している可能性があります。そして、それらはすべて(GPLであるbigint-cppパッケージとは異なり、BSDまたはLGPLのいずれかです)-それが重要かどうかはわかりません-しかし、それは多くの問題かもしれません。

カスタムのuint128_t種類のタイプを書くこともできます。通常、このようなクラスは、通常のMPIクラスと同じアルゴリズムを実装します。2つまたは4つの要素のみを持つようにハードコーディングされています。 応用暗号ハンドブックの第14章

もちろん、実際にすべての算術演算を必要としない場合は、手動でこれを行う方が簡単です(特に、除算とモジュロはかなり扱いにくいです)。たとえば、64ビットを仮想的にオーバーフローさせる可能性のあるカウンタを追跡する必要がある場合、64ビットの長いlongのペアとしてそれを表現し、手動でキャリーを実行できます。

unsigned long long ctrs[2] = { 0 };

void increment() {
   ++ctrs[0];
   if(!ctrs[0]) // overflow
     ++ctrs[1];
}

もちろん、一般的なMPIパッケージまたはカスタムuint128_tクラスよりもはるかに簡単に処理できます。

20
Jack Lloyd

Boostのデータ型は multiprecision 128〜1024ビットの範囲のタイプのライブラリにあります。

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t mySignedInt128 = -1;
uint128_t myUnsignedInt128 = 2;
int256_t mySignedInt256 = -3;
uint256_t myUnsignedInt256 = 4;
int512_t mySignedInt512 = -5;
uint512_t myUnsignedInt512 = 6;
int1024_t mySignedInt1024 = -7;
uint1024_t myUnsignedInt1024 = 8;
9
Tuxdude

GCC supports それをサポートするプロセッサー用の128ビット整数型。以下を使用してアクセスできます。

__int128          a;
unsigned __int128 b;
4
Richard

車輪を再発明しないでください-私は他の人がすでにこの問題を解決していると確信していますが、私の頭の上の解決策を挙げることはできません。 [〜#〜] gmp [〜#〜] は固定サイズの整数ではやり過ぎですが、使用するのが少し面倒ですが、確実に問題を解決できます(C++ではなくCライブラリです) 。

2
Adam Rosenfield

試してみてください [〜#〜] gmp [〜#〜]

2
Burkhard

これは私がグーグルで見つけたライブラリです。

http://sourceforge.net/projects/cpp-bigint/

0
Daniel A. White

サイズを大きくするシーケンスよりも、無限精度の整数クラスを使用した方がよい場合があります。一部の言語(Common LISPやIIRC Pythonなど)にはネイティブに含まれています。 C++で何が利用できるかわからない。最後に、Boostバージョンがないことを確認しました。

0
David Thornley

Cairoグラフィックライブラリには、移植可能な128ビット整数演算を実装する2つのファイルがあります:cairo-wideint-private.h、cairo-wideint.c。この2つだけをプロジェクトに含めて、128ビットを取得します。

0
pdbj