如何在C++中设计 16、32、64 字节甚至更大的 INT

How to design INT of 16,32, 64 bytes or even bigger in C++

本文关键字:字节 INT C++      更新时间:2023-10-16

作为初学者,我知道如果需要,我们可以使用ARRAY来存储更大的数字,但我希望在 c++ 中有一个16 bytesINT数据类型,我可以在它上执行所有算术运算,就像对基本数据类型(如INTFLOAT

因此,我们实际上可以根据需要增加默认数据类型的大小,例如 64 字节的int或 120 字节的double,不是直接针对基本数据类型,而是实际上与增加数据类型容量相同。

这甚至可能吗,如果是,那么如何以及如果不是,那么实现相同的完全不同的方法是什么?

是的,这是可能的,但不,这不是微不足道的。

首先,我觉得有必要指出,在这个领域,C 和 C++ 确实没有像你真正想要的那样在最低级别提供对硬件的访问。在汇编语言中,您通常会得到一些功能,这些功能使多精度算术更容易实现。一个是携带标志。这跟踪先前的加法是否生成了进位(或先前的减去借款(。因此,要在具有 64 位寄存器的机器上添加两个 12 位数字,您通常需要按照以下一般顺序编写代码:

; r0 contains the bottom 64-bits of the first operand
; r1 contains the upper 64 bits of the first operand
; r2 contains the lower 64 bits of the second operand
; r3 contains the upper 64 bits of the second operand
add r0, r2
adc r1, r3

同样,当您将两个数字相乘时,大多数处理器会在两个单独的寄存器中生成完整的答案,因此当您(例如(将两个 64 位数字相乘时,您会得到 128 位的结果。

然而,在 C 和 C++ 中,我们没有得到这一点。解决它的一种简单方法是在较小的块中工作。例如,如果我们想要一个提供 64 位long long作为其最大整数类型的实现上的 128 位类型,我们可以在 32 位块中工作。当我们要做一个手术时,我们把它们扩大到一个long long,并在long long上做手术。这样,当我们添加或相乘两个 32 位块时,如果结果大于 32 位,我们仍然可以将其全部存储在我们的 64 位long long.

因此,对于附加功能,生活非常容易。我们添加两个最低顺序的单词。我们使用位掩码来获取底部的 32 位,并将它们存储到结果的底部 32 位中。然后我们取上面的 32 位,并在添加操作数的下一个 32 位时将它们用作"进位"。继续,直到我们添加了所有 128(或其他(操作数位并得到我们的整体结果。

减法非常相似。事实上,我们可以在第二个操作数上做 2 的补码,然后加法得到我们的结果。

乘法变得有点棘手。我们如何在较小的部分进行乘法并不总是很明显的。通常基于分配属性。也就是说,我们可以取一些大数 A 和 B,并将它们分解为 (a 0 + a1( 和 (b0+ b1(,其中每个 a n 和 bn都是操作数的32 位块。然后我们使用分配属性将其转换为:

A 0 * B 0 + A 0 * B 1 + A 1 * B0+ a 1 * B1

这可以扩展到任意数量的"块",尽管如果您正在处理非常大的数字,则有更好的方法(例如,karatsuba(。

如果要定义非原子大整数,可以使用纯结构。

template <std::size_t size>
struct big_int {
std::array<std::int8_t, size> bytes;
};
using int128_t = big_int<16>;
using int256_t = big_int<32>;
using int512_t = big_int<64>;
int main() {
int128_t i128 = { 0 };
}