如何找到硬件算法完全支持的最大整数

How do I find the largest integer fully supported by hardware arithmetics?

本文关键字:支持 整数 何找 硬件 算法      更新时间:2023-10-16

我正在实现一个BigInt类,该类必须支持对整数的任意精度运算。

引用S.Skiena的"算法设计手册":

我应该做什么基础[编者按:任意精度]算术-用十进制实现自己的高精度算术包可能是最简单的,因此可以将每个整数表示为以10为基数的字符串。然而,使用更高的基数要有效得多,理想情况下等于硬件算术完全支持的最大整数的平方根。

如何找到硬件算术完全支持的最大整数?如果我理解正确,作为一台基于x64的电脑,支持的最大整数应该是2^64(http://en.wikipedia.org/wiki/X86-64-体系结构功能:64位整数功能),所以我应该使用base2^32,但在c++中有没有一种方法可以通过编程获得这个大小,这样我就可以为它键入base_type?

您可能正在搜索std::uintmax_tstd::intmax_t

static_cast<unsigned>(-1)是最大int。例如,所有位都设置为1。这就是您想要的吗?

您也可以使用std::numeric_limits<unsigned>::max()UINT_MAX,所有这些都将产生相同的结果。并且这些值所表示的是CCD_ 7类型的最大容量。例如可以存储为无符号类型的最大值。

int(扩展为unsigned int)是体系结构的"自然"大小。因此,一个具有int一半位的类型应该工作得相当好。除此之外,您还需要针对特定的硬件进行配置;存储单元的类型和计算单元的类型应当是报头中的typedefs,并且选择它们的类型以匹配特定处理器。通常情况下,您会在运行一些速度测试后做出此选择。

INT_MAX在这里没有帮助;它告诉可以存储在int中的最大值,这可能是硬件可以直接支持的最大值也可能不是。同样,INTMAX_MAX也无济于事;它告诉您可以存储为积分类型的最大值,但不告诉您对这样的值的操作是否可以在硬件中完成或需要软件模拟。

在过去,经验法则是直接在硬件中对int进行操作,而对long的操作是作为多个整数操作进行的,因此对long进行的操作比对int的操作慢得多。这不再是一个好的经验法则。

事情并不是那么非黑即白。这里有五月的问题,你可能还有其他值得考虑的事情。我现在已经编写了两个可变精度工具(在MATLAB、VPI和HPF中),并在每个工具中选择了不同的方法。这也关系到你是在写整数形式还是高精度浮点形式

不同的是,整数可以在没有位数限制的情况下增长。但是,如果您使用用户指定的位数执行浮点实现,那么您总是知道尾数中的位数。这是固定的。

首先,对每个十进制数字使用一个整数是最简单的。这使得很多事情都能很好地工作,所以I/O很容易。不过,它在存储方面有点低效。不过,加减法很简单。如果你对每个数字使用整数,那么乘法就更容易了。例如,在MATLAB中,conv是相当快的,尽管它仍然是O(n^2)。我认为gmp使用fft乘法,所以速度更快。

但是,假设您使用基本的conv乘法,那么您需要担心具有大量数字的数字会溢出。例如,假设我将十进制数字存储为8位有符号整数。使用conv,后面跟着进位,我可以做乘法。例如,假设我的数字是9999。

N = repmat(9,1,4)
N =
     9     9     9     9
conv(N,N)
ans =
    81   162   243   324   243   162    81

因此,即使要形成9999*9999的乘积,我也需要小心,因为数字会溢出一个8位有符号整数。如果我使用16位整数来累积卷积乘积,那么一对1000位整数之间的乘积可能会导致溢出。

N = repmat(9,1,1000);
max(conv(N,N))
ans =
       81000

因此,如果你担心数百万数字的可能性,你需要小心。

一种选择是使用我所说的migits,基本上是在高于10的基数下工作。因此,通过使用基数1000000和doubles来存储元素,我可以为每个元素存储6个十进制数字。不过,对于较大的数字,卷积仍然会导致溢出。

N = repmat(999999,1,10000);
log2(max(conv(N,N)))
ans =
       53.151

因此,长度为10000 migits(60000位十进制数字)的两组基数为1000000的migits之间的卷积将溢出双精度不能准确表示整数的点。

所以,如果你要使用数百万位数的数字,要小心。在基于卷积的乘法中使用更高基的migits的一个好处是,由于conv运算是O(n^2),那么从基数10到基数100会使速度提高4-1。以1000为基数会在卷积中产生9-1的加速。

最后,使用10以外的基数作为migits使实现保护数字(用于浮点运算)变得合乎逻辑。在浮点运算中,您永远不应该相信计算的最低有效位,因此将几个数字隐藏在阴影中是有意义的。因此,当我编写HPF工具时,我让用户控制将携带多少数字。当然,这不是整数的问题。

还有许多其他问题。我在这些工具附带的文档中讨论了它们。