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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18766535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 11:45:38  来源:igfitidea点击:

Positive integer from Python hash() function

pythonhashcross-platform

提问by Craig McQueen

I want to use the Python hash()function to get integer hashes from objects. But built-in hash()can give negative values, and I want only positive. And I want it to work sensibly on both 32-bit and 64-bit platforms.

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

I.e. on 32-bit Python, hash()can return an integer in the range -2**31to 2**31 - 1. On 64-bit systems, hash()can return an integer in the range -2**63to 2**63 - 1.

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

But I want a hash in the range 0to 2**32-1on 32-bit systems, and 0to 2**64-1on 64-bit systems.

但我想的范围内的散列02**32-1在32位系统,以及02**64-1在64位的系统。

What is the best way to convert the hash value to its equivalent positive value within the range of the 32- or 64-bit target platform?

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

(Context: I'm trying to make a new random.Randomstyle class. According to the random.Random.seed()docs, the seed "optional argument x can be any hashable object." So I'd like to duplicate that functionality, except that my seed algorithm can't handle negative integer values, only positive.)

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

采纳答案by falsetru

Using sys.maxsize:

使用sys.maxsize

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

Alternative using ctypes.c_size_t:

替代使用ctypes.c_size_t

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

回答by unwind

How about:

怎么样:

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

This uses sys.maxsizeto be portable between 32- and 64-bit systems.

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

回答by Voo

Just using sys.maxsizeis wrong for obvious reasons (it being `2*n-1 and not 2*n), but the fix is easy enough:

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

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

for performance reasons you may want to split the sys.maxsize + 1 into two separate assignments to avoid creating a long integer temporarily for most negative numbers. Although I doubt this is going to matter much

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

回答by Mark Ransom

(Edit: at first I thought you always wanted a 32-bit value)

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

Simply AND it with a mask of the desired size. Generally sys.maxsizewill already be such a mask, since it's a power of 2 minus 1.

简单地将它与所需大小的掩码一起使用。通常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