4 题: 来自Python hash()函数的正整数

在...创建的问题 Thu, Sep 12, 2013 12:00 AM

我想使用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()文档,种子“可选参数x可以是任何可散列对象。”所以我想复制该功能,除了我的种子算法不能处理负整数值,只有正数。)

    
18
4个答案                              4 跨度>                         

使用 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
    
17
2013-09-12 14:38:56Z
  1. 如果sys.maxsize2**322**64,那将是美好而简单和可靠的。但sys.maxsize实际上是2**31-12**63-1
    2013-09-12 14:18:24Z
  2. 我想我可以使用(sys.maxint + 1) * 2)并希望最好。
    2013-09-12 14:20:22Z
  3. @ CraigMcQueen,你是对的。我更新了代码。谢谢。
    2013-09-12 14:24:04Z
  4. 这里没有任何理由使用模数。我的意思是确定它有效,但效率较低,难以阅读。
    2013-09-12 14:24:35Z
  5. @ CraigMcQueen,我添加了一种替代方法。看看吧。
    2013-09-12 14:41:13Z
  6. 醇>

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

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

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

    
3
2013-09-12 14:38:46Z
  1. 您的代码可能会产生重复的值。在64位系统中试用-0x7fffffffffffffff + sys.maxsize + 1
    2013-09-12 14:35:33Z
  2. 啊是的,不应该是有条件的。我今天在哪里?
    2013-09-12 14:38:39Z
  3. 为什么/2而不是*2
    2013-09-12 14:40:18Z
  4. 实际上它既不是/也不是* 2.我们有[-2**31, 2**31-1]的范围,但我们想要[-2**31+2**31, 2**31-1+2**31](例如是32位系统)。所以'只是下边界的一个附加物(2 ** 31)..我今天真的很困惑。
    2013-09-12 14:41:47Z
  5. 我看到了中间代码。
    2013-09-12 14:43:33Z
  6. 醇>

怎么样:

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

这使用 sys.maxsize 可在32-和64位系统。

    
1
2013-09-12 14:14:40Z
  1. 我认为结果的范围是-12**31 - 1(32位)或-12**63 - 1(64位)。
    2013-10-11 01:32:00Z
  2. 醇>

(编辑:起初我以为你总是想要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
    
1
2013-09-12 19:51:04Z
  1. 这是一个好主意,虽然我想要一个64位(或32位)值,而不是63位(或31位)值。
    2013-09-13 01:24:25Z
  2. @ CraigMcQueen,抱歉我认为maxsize的尺寸已经合适了。
    2013-09-13 02:05:24Z
  3. 醇>
来源放置 这里