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

时间:2012-08-18 12:06:45

标签: c++ math arbitrary-precision

我正在实现一个必须支持对整数进行任意精度操作的BigInt类。

引自S.Skiena的“算法设计手册”:

  

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

如何找到硬件算法完全支持的最大整数?如果我理解正确,作为我的机器是基于x64的PC,支持的最大整数应该是2 ^ 64(http://en.wikipedia.org/wiki/X86-64-建筑特征:64 -bit整数能力),所以我应该使用base 2 ^ 32,但是在c ++中是否有一种方法可以以编程方式获得这个大小,所以我可以为它输入我的base_type?

4 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:2)

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

您还可以使用std::numeric_limits<unsigned>::max()UINT_MAX,所有这些都会产生相同的结果。这些值告诉的是unsigned类型的最大容量。例如可以存储到无符号类型的最大值。

答案 2 :(得分:1)

事情并非如此黑白分明。这里有五个问题,您可能还有其他值得考虑的事情。我现在写了两个变量精度工具(在MATLAB中,VPIHPF),我在每个工具中都选择了不同的方法。无论是编写整数形式还是高精度浮点形式,这都很重要。

不同之处在于,整数可以在不受数字位数限制的情况下增长。但是,如果您使用用户指定的位数进行浮点实现,则始终知道尾数中的位数。这是固定的。

首先,对每个十进制数字使用单个整数是最简单的。这使得很多东西很好用,所以I / O很容易。但是在存储方面它有点低效。尽管如此,添加和减少都很简单。如果你对每个数字使用整数,那么乘法甚至很容易。例如,在MATLAB中,conv非常快,尽管它仍然是O(n ^ 2)。我认为gmp使用fft乘法,所以更快。

但是假设您使用基本转换乘法,那么您需要担心具有大量数字的数字的溢出。例如,假设我将十进制数字存储为8位有符号整数。使用conv,然后使用carry,我可以做多次。例如,假设我的号码为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以上的基础上。因此,通过使用base 1000000和double来存储元素,我可以为每个元素存储6个十进制数字。卷积仍然会导致更大数字的溢出。

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

因此,两组基本1000000个迁移(长度为10000个迁移(60000个十进制数字))之间的卷积将溢出双精度不能完全表示整数的点。

再次,如果您将使用数百万位的数字,请注意。使用基于卷积的乘法的更高基数的迁移是一个好处,因为转换操作是O(n ^ 2),然后从基数10到基数100给你4-1加速。进入基数1000会在回合中产生9-1的加速。

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

还有很多其他问题。我在用这些工具进行的文档中讨论它们。

答案 3 :(得分:1)

int(并且,扩展名为unsigned int)是架构的“自然”大小。因此,具有int的一半位的类型应该工作得相当好。除此之外,您确实需要配置特定的硬件;存储单元的类型和计算单元的类型应该是标头中的typedef,并且选择它们的类型以匹配特定的处理器。通常,您在运行一些速度测试后进行此选择。

INT_MAX在这里没有帮助;它告诉你可以存储在int中的最大值,它可能是也可能不是硬件可以直接支持的最大值。同样,INTMAX_MAX也没有帮助;它告诉您可以存储为整数类型的最大值,但不会告诉您对这样的值的操作是在硬件中完成还是需要软件仿真。

回到过去,经验法则是对int的操作是直接在硬件中完成的,longs上的操作是作为多个整数操作完成的,因此longs上的操作比int上的操作要慢得多。这不再是一个好的经验法则。