11

我遇到的问题是创建一种大整数库。我想让它既跨平台又尽可能快。这意味着我应该尝试使用系统本机支持的大数据类型进行数学运算。

我实际上并不想知道我是为 32 位还是 64 位系统编译;我所需要的只是一种根据可用的最大值创建 64 位或 32 位或任何位整数的方法。我将使用 sizeof 来表现不同,具体取决于那是什么。

以下是一些可能的解决方案及其问题:

使用 sizeof(void*):这给出了指向内存的指针的大小。系统有可能(尽管不太可能)具有比它能够进行数学运算更大的指向内存的指针,反之亦然。

始终使用 long:虽然在多个平台上,长整数确实是 4 字节或 8 字节,具体取决于体系结构(我的系统就是这样一个例子),但即使在 64 位系统上,一些编译器也将长整数实现为 4 字节。

始终使用 long long:在许多 32 位系统上,这是一个 64 位整数,它可能效率不高(尽管可能比我编写的任何代码都更有效)。真正的问题是,某些架构可能根本不支持它(例如为我的 mp3 播放器供电的架构)。

需要强调的是,我的代码不关心整数的实际大小,一旦它被选择(它依赖于 sizeof() 来处理大小重要的任何事情)。我只希望它选择能使我的代码最有效的整数类型。

4

4 回答 4

7

如果你真的想要一个原生大小的类型,我会使用size_t,ptrdiff_tintptr_tand uintptr_t。在任何非病理系统上,这些都将是本机字长。

另一方面,在简单性方面总是使用固定大小肯定有好处,在这种情况下,我会使用int32_tuint32_t. 我说它更简单的原因是您通常最终需要知道诸如“适合该类型的 10 的最大幂”(用于十进制转换)和其他不能容易地根据类型表示为常量表达式的常量你用过。如果您只选择固定数量的位,您还可以修复方便的常量(如我的示例中的 1000000000)。当然,这样做会牺牲一些高端系统的性能。您可以采取相反的方法并使用更大的固定大小(64 位),这在高端系统上是最佳的,并假设编译器在 32 位机器上的 64 位算术代码至少与您的 bignum 代码处理 2 个 32 位字,在这种情况下它仍然是最佳的。

于 2010-12-29T02:54:39.770 回答
4

最好的方法不是依赖自动检测,而是针对特定的编译器使用一组#if/#else语句来选择你已经测试过并且知道是最优的类型。

于 2010-12-29T00:04:03.753 回答
0

以下是我们bsdnt中的做法:

#if ULONG_MAX == 4294967295U

typedef uint32_t word_t;
typedef unsigned int dword_t __attribute__((mode(DI)));
#define WORD_BITS 32

#else

typedef uint64_t word_t;
typedef unsigned int dword_t __attribute__((mode(TI)));
#define WORD_BITS 64

#endif

如果有兴趣,发起该项目的人写了一篇关于编写 bignum 库的博客。

GMP/MPIR 要复杂得多;gmp-h.in 变成 gmp.h 后配置,它定义了这个:

#define GMP_LIMB_BITS                      @GMP_LIMB_BITS@

简而言之,长度设置为构建过程的一部分,通过config.guess(即自动工具)解决。

于 2010-12-29T00:11:35.150 回答
0

使用stdint.h中的 int_fast32_t似乎是一种选择,尽管对于“快速”的含义,您受那些决定者的摆布。

于 2010-12-29T00:46:24.890 回答