10

I would like to map values returned by Python's hash() function to floats in the range 0 to 1. On my system I can do this with

scale = 1.0/(2**64)
print hash(some_object)*scale+0.5

However, I know this will be different on 32-bit systems. Most likely I will never run this code anywhere else, but still I would like to know if there's a way to programmatically determine the maximum and minimum values that Python's built-in hash() function can return.

(By the way the reason I'm doing this is that I'm developing a numerical simulation in which I need to consistently generate the same pseudo-random number from a given Numpy array. I know the built-in hash won't have the best statistics for this, but it's fast, so it's convenient to use it for testing purposes.)

4

4 回答 4

8

在 Python 2.7中hash()返回一个int,因此sys.maxint应该让您了解它的范围。

于 2013-10-02T09:25:37.773 回答
2

这实际上并不是对您的主要问题的回答,而是对您的细则的回答。numpyRNG 将numpy数组作为种子(在内部散列它们):

>>> import numpy
>>> a = numpy.arange(1000)
>>> b = a.copy()
>>> b[-1] = 0
>>> r1 = numpy.random.RandomState(a)
>>> r2 = numpy.random.RandomState(b)
>>> r3 = numpy.random.RandomState(a)
>>> r1.rand()
0.9343370187421804
>>> r3.rand()
0.9343370187421804
>>> r2.rand()
0.4651506189783071
于 2013-10-02T10:45:24.460 回答
1

hash()调用传入对象的__hash__钩子。该钩子应该返回一个整数。

因为 Python只受内存大小的限制,所以理论上可以返回int的值没有真正的上限。hash()

如果您想跟踪 Python 对象如何实现这一点,请在目录tp_hash中搜索槽,或查找函数调用以查看这些槽的值如何被集合、字典和其他代码使用。Objects/PyObject_Hash

CPython long integer 对象本身将返回值限制为 C long int。

此外,CPythontype tp_hash函数将从 Python__hash__函数返回的任何大于 C long int 范围之外的值转换为该值的 Python long int 哈希值;因此,大于 的哈希值sys.maxint将通过再次hash()调用该值进行转换。

所以在实践中,hash() 应该返回的值限制为sys.maxint.

在 Python 3 中,引入了一种新类型,Py_hash_t; C long 在某些 64 位平台上仍然仅限于 32 位,但Py_hash_t与指针大小相同,在任何 64 位平台上都为您提供 64 位。在 Python 3 上,该sys.maxsize值正确反映了最大值;它返回平台上的指针可以容纳的最大值。

于 2013-10-02T09:23:35.070 回答
1

Python >= 3.2sys.hash_info返回一个命名元组,其中包含一个width具有哈希值位宽的键。示例:(添加换行符以提高可读性)

Python 3.7.3 (default, Jul 25 2020, 13:03:44) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.hash_info
sys.hash_info(
    width=64,
    modulus=2305843009213693951,
    inf=314159,
    nan=0,
    imag=1000003,
    algorithm='siphash24',
    hash_bits=64,
    seed_bits=128,
    cutoff=0
)

如图所示,我机器上的 Python 使用 64 位哈希。

请注意,如果一个类实现__hash__()但返回一个超出此位宽的整数,它将被简单地截断

于 2021-01-31T13:37:44.663 回答