找出当前平台上最大的原生整数类型

发布于 2024-10-09 04:40:25 字数 593 浏览 0 评论 0原文

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

我实际上不想知道我是针对 32 位还是 64 位系统进行编译;我所需要的只是一种根据可用的最大整数创建 64 位或 32 位或任何位整数的方法。我将使用 sizeof 来根据具体情况进行不同的行为。

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

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

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

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

强调一下,一旦选择了整数,我的代码并不关心整数的实际大小是多少(对于大小重要的任何内容,它都依赖于 sizeof() )。我只是希望它选择将使我的代码最高效的整数类型。

The problem I have is to create a sort of big integer library. I want to make it both cross platform and as fast as possible. This means that I should try to do math with as large data types as are natively supported on the system.

I don't actually want to know whether I am compiling for a 32 bit or 64 bit system; all I need is a way to create a 64 bit or 32 bit or whatever bit integer based on what is the largest available. I will be using sizeof to behave differently depending on what that is.

Here are some possible solutions and their problems:

Use sizeof(void*):
This gives the size of a pointer to memory. It is possible (though unlikely) that a system may have larger pointers to memory than it is capable of doing math with or vice versa.

Always use long:
While it is true that on several platforms long integers are either 4 bytes or 8 bytes depending on the architecture (my system is one such example), some compilers implement long integers as 4 bytes even on 64 bit systems.

Always use long long:
On many 32 bit systems, this is a 64 bit integer, which may not be as efficient (though probably more efficient than whatever code I may be writing). The real problem with this is that it may not be supported at all on some architectures (such as the one powering my mp3 player).

To emphasize, my code does not care what the actual size of the integer is once it has been chosen (it relies on sizeof() for anything where the size matters). I just want it to choose the type of integer that will cause my code to be most efficient.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浮萍、无处依 2024-10-16 04:40:25

如果您确实想要本机大小的类型,我会使用 size_tptrdiff_tintptr_tuintptr_t。在任何非病态系统上,这些都将是本机字大小。

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

If you really want a native-sized type, I would use size_t, ptrdiff_t, or intptr_t and uintptr_t. On any non-pathological system, these are all going to be the native word size.

On the other hand, there are certainly benefits in terms of simplicity to always working with a fixed size, in which case I would just use int32_t or uint32_t. The reason I say it's simpler is that you often end up needing to know things like "the largest power of 10 that fits in the type" (for decimal conversion) and other constants that cannot be easily expressed as constant expressions in terms of the type you've used. If you just pick a fixed number of bits, you can also fix the convenient constants (like 1000000000 in my example). Of course by doing it this way, you do sacrifice some performance on higher-end systems. You could take the opposite approach and use a larger fixed size (64 bits), which would be optimal on higher-end systems, and assume that the compiler's code for 64-bit arithmetic on 32-bit machines will be at least as fast as your bignum code handling 2 32-bit words, in which case it's still optimal.

榆西 2024-10-16 04:40:25

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

The best way is not to rely on automatic detection, but to target specific compilers with a set of #if/#else statements to choose a type that you have tested and know to be optimal.

归途 2024-10-16 04:40:25

这是 我们是如何做到的 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(即自动工具)来计算。

Here's how we did it in 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

If it's of interest, the guy who initiated the project has written a blog on writing bignum libraries.

GMP/MPIR is massively more complicated; gmp-h.in becomes gmp.h post-configure which defines this:

#define GMP_LIMB_BITS                      @GMP_LIMB_BITS@

In short, the length is set as part of the build process which works it out via config.guess (i.e. autotools).

甩你一脸翔 2024-10-16 04:40:25

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

Using int_fast32_t from stdint.h would seem to be an option, although you are at the mercy of Those Who Decide, as to what "fast" means.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文