将一组三个整数编码为一个唯一数字

时间:2019-02-21 18:49:40

标签: java

所以,我的问题很简单。我正在使用从 [0-65535] 中随机选择的一组三个整数,我的工作是将这些整数编码为一个唯一的数字。到目前为止,这是我尝试过的

我已经编写了一个名为pack的Java函数,尝试按以下方式对该数字进行编码

 private long pack(long a, long b, long c) {
        int N = 65535, M = 65536;
        return (a + (b * N) + c * N * M);
    }

我还写了另一个java函数,将打包的数字解压缩或解码回原始整数,如下所示:

private long[] unpack(long packed) {
    int N = 65535, M = 65536;
    long a = (packed % N);
    long b = (packed / N) % M;
    long c = (packed % (N * M));
    return new long[]{a, b, c};
}

现在,当我使用示例数据{67, 8192, 7168}在main函数中运行以上代码时,在控制台输出中得到以下结果

Packing 67, 8192, 7168
Result=30786392678467

UnPacking 30786392678467
Result=[67, 8192, 57411]

从上面可以明显看出,我的第一个和第二个值始终正确,但是最后一个值似乎总是错误的。我可能会错过什么。非常感谢您的帮助。非常感谢。

3 个答案:

答案 0 :(得分:4)

我现在将为您提供替代解决方案,然后当我使用PC而不是手机(rgettman beat me!)时,我可以尝试调试当前的解决方案。

因为三个数字中的每个数字最多可以为65535,这意味着每个数字将适合16位。因此,您可以使用以下命令简单地构建唯一的long

long encoded = (a << 32L) | (b << 16) | c;

并对其进行解码,如下所示:

long a = (encoded >> 32) & 0xFFFFL;
long b = (encoded >> 16) & 0xFFFFL;
long c = encoded & 0xFFFFL;

答案 1 :(得分:3)

根据您指定的范围[0,65535],您的包装和拆包代码不正确。

有65,536个可能的数字,并且您不希望一个整数的编码更改另一个整数的编码。您应该使用一个设置为65536的常量(即2 16 )。

public static final long PACK = 65536;

然后,您的pack方法会稍微更改为:

private long pack(long a, long b, long c) {
    return (a + (b * PACK) + c * PACK * PACK);
}

a打包到long的最低有效16位(第49-64位),b打包到第33-48位,c打包到第17-32位。 (0-16中没有包含任何内容,因此这些位保持清除状态。)

此外,您的unpack方法更改为:

private static long[] unpack(long packed) {
    long a = (packed % PACK);
    long b = (packed / PACK) % PACK;
    long c = (packed / (PACK * PACK));  // Use / not %.
    return new long[]{a, b, c};
}

请注意,c的运算除以PACK的平方,而不使用%运算符,而是使用/。否则MN都被PACK取代。

具有以下更改的输出:

Packing 67, 8192, 168
Result=722091376707

UnPacking 722091376707
Result=[67, 8192, 168]

答案 2 :(得分:1)

实际上,您的解决方案几乎是正确的:只需确保M == N == 65536并解决解压缩变量 c 的问题。

catch exceptionorg.elasticsearch.hadoop.EsHadoopIllegalArgumentException: Incompatible types found in multi-mapping: Field [fieldName] has conflicting types of [LONG] and [INTEGER]

此外,我将N的类型更改为 long ,尽管这无关紧要,因为Java仍会在乘法过程中将其转换为 long