1

我有无符号 64 位整数,我想将其用作 App Engine 数据存储区密钥。不幸的是,NDB 数据存储 API 似乎只允许有符号的 64 位整数,最大大小为pow(2, 63).

我可以对整数进行二进制补码,但我依赖数据存储中的排序顺序进行查询,所以我希望0xffffffffffffffff0x0升序排序而不是在它之前。我相信如果我对我的 64 位无符号整数进行二进制补码,就会发生这种情况,因为数据存储区索引会0xffffffffffffffff解释为这种整数,并且会被解释为例如。-10x00

我可以将每个无符号 64 位密钥从整数更改为字符串甚至十六进制字符串,但这会比将密钥保留为 64 位整数占用更多的数据存储空间。

4

2 回答 2

2

感谢Tim HoffmanGuido van Rossum,答案是您不能使用 64 位无符号整数作为 App Engine 数据存储区中的实体键并保留排序顺序。

如果您不关心排序顺序,那么您可以对无符号 64 位整数进行二进制补码并使用它。

最后,我将无符号的 64 位整数更改为固定宽度的十六进制字符串,并将其保存为键,因为它似乎最方便,但会牺牲一些空间。

我使用的函数如下所示:

def to_hex_string(unsigned_64bit_int):
    return '{:016x}'.format(my_unsigned_64bit_int)

def to_unsigned_64bit_int(hex_string):
    return int(hex_string, 16)

如果空间很重要,Guido van Rossum建议使用保留排序顺序的 base-64 编码。我不确定 Python base64 模块编码器是否保留排序顺序。

于 2013-07-19T12:46:45.623 回答
0

只需将您的无符号值编码为具有简单常量偏移量的有符号值pow(2, 63)

这会将所有值“向下”“移动”而不会弄乱排序顺序,从无符号 64 位整数可表示的 [0, 2^64) 范围到可表示的范围 [-2^63, 2^63) ( a) 有符号 64 位整数的典型实现。

def encode(unsigned_64_bit_int):
    return unsigned_64_bit_int - pow(2, 63)

def decode(signed_64_bit_int):
    return signed_64_bit_int + pow(2, 63)

(如果您发现它更清晰或以某种重要的方式影响性能,您也可以pow(2, 63)用等效的常量替换。)0x8000000000000000

于 2021-03-11T23:43:13.340 回答