来自Python hash()函数的正整数

时间:2013-09-12 14:07:22

标签: python hash cross-platform

我想使用Python hash()函数从对象中获取整数哈希值。但是内置的hash()可以给出负值,而我只想要积极的。我希望它能够在32位和64位平台上合理地工作。

即。在32位Python上,hash()可以返回-2**312**31 - 1范围内的整数。 在64位系统上,hash()可以返回-2**632**63 - 1范围内的整数。

但我希望32位系统上的02**32-1范围内的哈希值,以及64位系统上的02**64-1

将哈希值转换为32位或64位目标平台范围内的等效正值的最佳方法是什么?

(上下文:我正在尝试创建一个新的random.Random样式类。根据random.Random.seed() docs,种子“可选参数x可以是任何可清除对象。”所以我想复制该功能,但我的种子算法无法处理负整数值,只有正数。)

4 个答案:

答案 0 :(得分:17)

使用sys.maxsize

>>> import sys
>>> sys.maxsize
9223372036854775807L
>>> hash('asdf')
-618826466
>>> hash('asdf') % ((sys.maxsize + 1) * 2)
18446744073090725150L

使用ctypes.c_size_t替代方案:

>>> import ctypes
>>> ctypes.c_size_t(hash('asdf')).value
18446744073090725150L

答案 1 :(得分:3)

仅仅使用sys.maxsize是错误的,原因很明显(它是'2 * n-1而不是2 * n),但修复很容易:

h = hash(obj)
h += sys.maxsize + 1

出于性能原因,您可能希望将sys.maxsize + 1拆分为两个单独的分配,以避免为大多数负数暂时创建一个长整数。虽然我怀疑这很重要

答案 2 :(得分:1)

怎么样:

h = hash(o)
if h < 0:
  h += sys.maxsize

这使用sys.maxsize可在32位和64位系统之间移植。

答案 3 :(得分:1)

(编辑:起初我以为你总是想要32位值)

只需使用所需尺寸的面罩即可。通常sys.maxsize已经是这样的掩码,因为它是2减1的幂。

import sys
assert (sys.maxsize & (sys.maxsize+1)) == 0 # checks that maxsize+1 is a power of 2 

new_hash = hash & sys.maxsize