如何将三个整数组合成一个唯一的标记,使标记在c++中保持整数

How to combine three integers into one unique tag, such that the tag stays integer in C++?

本文关键字:整数 c++ 三个 组合 一个 唯一      更新时间:2023-10-16

我尝试使用Cantor和Szuszik配对函数,但例如a = 200, b=201 c=202结果P(a,b,c) = P(P(a,b),c),它已经是一个非常大的数,无法放入int中。

在[0:1000]范围内唯一组合三个数字是没有问题的(假设int在您的系统上是32位或更大):

int combine(int a, int b, int c)
{
    return (a << 20) | (b << 10) | c;
}

以后提取它们:

void unpack(int combined, int *a, int *b, int *c)
{
    *a = combined >> 20;
    *b = (combined >> 10) & 0x3ff;
    *c = combined & 0x3ff;
}

这种包装是安全的,因为1000小于210,所以这些数字总是适合10位。

如果所有整数大小相同,则不能唯一地将三个整数放入一个整数中。但是,您可以做的是将三个较小的整数放入一个较大的整数中。为了简洁起见,我将修改您的问题,说您正在尝试将4个16位整数打包成1个64位int(具有特定的需求使解决方案更清晰)。您可以修改解决方案以满足您的需求:

uint16_t a = 61000, b=60000, c=48000, d=32000;
uint64_t e = 0;
memcpy((char*)&e, &a, sizeof(a));
memcpy((char*)&e + (1*sizeof(b)), &b, sizeof(b));
memcpy((char*)&e + (2*sizeof(c)), &c, sizeof(c));
memcpy((char*)&e + (3*sizeof(d)), &d, sizeof(d));  

编辑:这是一个使用位操作符和位移位的更简洁的版本(它假设每个被打包的int只使用最不重要的16位)

uint64_t a = 61000, b=60000, c=48000, d=32000;
uint64_t e = 0;
e = (a << 48) | (b << 32) | (c << 16) | d;

如果整数的顺序很重要(所以tag(a,b,c) != tag(b,c,a)),您需要一个大小为N^3的标签,其中N是输入整数的最大值。N^3 -因为这是(a,b,c)可能出现的三组数。每个都必须映射到唯一的值。所以你需要你的标签能够保持N^3的值。映射可以通过以下方式完成:a + b * N + c * N^2