31

我想使用 Pythonhash()函数从对象中获取整数哈希值。但是内置hash()可以给出负值,我只想要正值。我希望它在 32 位和 64 位平台上都能正常工作。

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

但我想要一个范围02**32-132 位系统和64 位系统0上的哈希值。2**64-1

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

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

4

4 回答 4

28

使用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
于 2013-09-12T14:14:29.883 回答
7

sys.maxsize由于显而易见的原因(它是 `2* n-1 而不是 2 *n),只是使用是错误的,但修复很容易:

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

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

于 2013-09-12T14:21:16.043 回答
1

怎么样:

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

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

于 2013-09-12T14:14:40.237 回答
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
于 2013-09-12T14:28:31.667 回答