在C ++中表示128位数字的最佳方法是什么?它应该尽可能地与内置数值类型一致(即支持所有算术运算符等)。
我正在考虑构建一个具有2个64位或4个32位数的类。或者可能只是创建一个128位的内存块并自己完成所有操作。
是否有一些更简单/更标准的方法,或者我自己实施时不太可能搞砸的东西? :)
如果它可以扩展到256位,512位等等也会很好......
答案 0 :(得分:64)
编辑:当我第一次写这篇文章boost::multiprecision::uint128_t
时还没有。保留这个答案是出于历史原因。
我之前已经上过uint128课程,你可以在http://www.codef00.com/code/uint128.h查看。
它依赖于boost来自动提供数学运算符的所有变体,因此它应该支持本机unsigned int
类型的所有内容。
内置类型有一些小的扩展,例如使用如下字符串初始化它:
uint128_t x("12345678901234567890");
有一个方便的宏,它的工作方式类似于C99,你可以这样使用:
uint128_t x = U128_C(12345678901234567890);
答案 1 :(得分:21)
这有点特殊情况,特别是因为您没有指定您正在寻找的平台,但是使用GCC,您可以使用所谓的模式(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,以及Crypto++和Botan中用于加密代码的bigint包。当然还有GnuMP,它是规范的C MPI库(它确实有一个C ++包装器,虽然上次看到它时看起来很难记录)。所有这些都设计得很快,但也可能针对更大(1000+位)的数字进行调整,因此在128位时你可能会遇到很多开销。 (另一方面,你不说是否重要)。所有这些(与bigint-cpp包不同,它是GPL,是BSD或LGPL) - 不确定它是否重要 - 但它可能很重要。
您也可以编写自定义uint128_t类型;通常这样的类会实现与常规MPI类相同的算法,只需硬编码只有2或4个元素。如果您对如何实现此类算法感到好奇,那么很好的参考是Chapter 14 of the Handbook of Applied Cryptography
当然,如果你实际上并不需要所有算术运算(除法和模数,特别是相当棘手),那么手工操作会更容易。例如,如果你只需要跟踪一个可能假设溢出64位的计数器,你可以将它表示为一对64位长的long并手动执行:
unsigned long long ctrs[2] = { 0 };
void increment() {
++ctrs[0];
if(!ctrs[0]) // overflow
++ctrs[1];
}
当然,与一般的MPI包或自定义的uint128_t类相比,处理起来要简单得多。
答案 2 :(得分:13)
查看已开发的其他库。很多人都想在你面前这样做。 :d
答案 3 :(得分:9)
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;
答案 4 :(得分:4)
GCC supports是支持它的处理器的128位整数类型。您可以使用以下方式访问它:
__int128 a;
unsigned __int128 b;
答案 5 :(得分:2)
不要重新发明轮子 - 我很肯定其他人已经解决了这个问题,虽然我不能说出任何解决方案。 GMP肯定可以解决你的问题,虽然它对固定大小的整数来说太过分了,而且使用它也有点麻烦(它是一个C库,而不是C ++)。
答案 6 :(得分:2)
您可以尝试GMP
答案 7 :(得分:0)
这是我在google上找到的一个库。
答案 8 :(得分:0)
使用无限精度整数类可能会更好,而不是增加大小的序列。有些语言(如Common Lisp和IIRC Python)本身就有这些语言。我不确定哪些可用于C ++;最后我看到那里没有Boost版本。
答案 9 :(得分:0)
cairo图形库有两个文件,它们实现了便携式128位整数运算:cairo-wideint-private.h,cairo-wideint.c。我们在项目中只包含这两个,以获得128位。
答案 10 :(得分:-1)
在Visual Studio C ++中,有一种FLOAT128类型用于表示128位整数。它实现为:
#if defined(_M_IA64) && !defined(MIDL_PASS)
__declspec(align(16))
#endif
typedef struct _FLOAT128 {
__int64 LowPart;
__int64 HighPart;
} FLOAT128;
所以我不确定为它实现了什么数学运算