web-dev-qa-db-ja.com

C ++に128ビット整数はありますか?

128ビット長の [〜#〜] uuid [〜#〜] を変数に格納する必要があります。 C++には128ビットのデータ型がありますか?算術演算は必要ありません。値を非常に高速に簡単に保存および読み取りたいだけです。

C++ 11の新しい機能も問題ありません。

57
danijar

GCCおよびClangサポート__int128

32
doron

チェックアウト ブーストの実装

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t v = 1;

これは、特に算術演算を行う必要がある場合、文字列や配列よりも優れています。

37
Patrik Beck

GCCは__int128、128ビットを保持するのに十分な整数モードを持つターゲット(プロセッサ)でのみサポートされます。特定のシステムでは、sizeof()intmax_tおよびuintmax_tは、コンパイラとプラットフォームがサポートする最大値を決定します。

34
Onkar

質問には2つの部分があります。

1 .128-bin整数。 @PatrikBeckが示唆するようにboost::multiprecisionは、非常に大きな整数に適した方法です。

2. UUID/GUID/CLSIDまたは任意の名前で保存できます。この場合 boost::multiprecisionはお勧めできません。そのために設計された GUID構造 が必要です。クロスプラットフォームタグが追加されると、その構造をコードにコピーして次のようにすることができます。

struct GUID
{
    uint32_t Data1;
    uint16_t Data2;
    uint16_t Data3;
    uint8_t Data4[8];
};

この形式は、いくつかの内部的な理由によりMicrosoftによって定義されています。次のように単純化することもできます。

struct GUID
{
    uint8_t Data[16];
};

さまざまなものを処理できるオブジェクトよりも、単純な構造の方がパフォーマンスが向上します。とにかく、GUIDSを使用して数学を行う必要がないため、派手なオブジェクトは必要ありません。

8
ST3

Visual-C++には128ビット整数はありません。Microsoftの呼び出し規則では、RAX:EAXペアで2つの32ビット値のみを返すことができるためです。これは、2つの整数を乗算すると結果が2ワードの整数になるため、常に頭痛の種になります。ほとんどのロードアンドストアマシンは、2つのCPUワードサイズの整数での動作をサポートしていますが、4での動作にはソフトウェアハックが必要であるため、32ビットCPUは128ビット整数を処理できず、8ビットおよび16ビットCPUは64を実行できませんコストのかかるソフトウェアハックのない-ビット整数。 64ビットCPUは、通常、128ビットで動作します。これは、2つの64ビット整数を乗算すると128ビット整数が得られるため、GCCバージョン4.6は128ビット整数をサポートするためです。これは、1つの64ビットWordをリターンレジスタで返し、リファレンスを使用してもう1つを渡すといういハックを行う必要があるため、ポータブルコードの作成に問題があります。たとえば、浮動小数点数を Gris で高速に出力するには、次のように128ビットの符号なし乗算を使用します。

#include <cstdint>
#if defined(_MSC_VER) && defined(_M_AMD64)
#define USING_VISUAL_CPP_X64 1
#include <intrin.h>
#include <intrin0.h>
#pragma intrinsic(_umul128)
#Elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define USING_GCC 1
#if defined(__x86_64__)
#define COMPILER_SUPPORTS_128_BIT_INTEGERS 1
#endif
#endif

#if USING_VISUAL_CPP_X64
    UI8 h;
    UI8 l = _umul128(f, rhs_f, &h);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#Elif USING_GCC
    UIH p = static_cast<UIH>(f) * static_cast<UIH>(rhs_f);
    UI8 h = p >> 64;
    UI8 l = static_cast<UI8>(p);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#else
    const UI8 M32 = 0xFFFFFFFF;
    const UI8 a = f >> 32;
    const UI8 b = f & M32;
    const UI8 c = rhs_f >> 32;
    const UI8 d = rhs_f & M32;
    const UI8 ac = a * c;
    const UI8 bc = b * c;
    const UI8 ad = a * d;
    const UI8 bd = b * d;
    UI8 tmp = (bd >> 32) + (ad & M32) + (bc & M32);
    tmp += 1U << 31;  /// mult_round
    return TBinary(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs_e + 64);
#endif
  }
2
Cale McCollough

tBigIntegerテンプレートを使用して、このTBigInt <128、true>のようなテンプレート配列のビット範囲を符号付き128ビット整数にするか、TBigInt <128、false>を符号なし128ビット整数にするように設定します。おそらく返信が遅くなり、他の誰かがこの方法をすでに見つけていることを願っています。

0
Silanus

std::bitset<128>を使用することをお勧めします(いつでもusing UUID = std::bitset<128>;のようなことができます)。他の回答で提案されているカスタム構造体と同様のメモリレイアウトになる可能性がありますが、独自の比較演算子、ハッシュなどを定義する必要はありません。

0