31

hash()Python関数を使用して、オブジェクトから整数ハッシュを取得したいと考えています。しかし、ビルトインhash()は負の値を与える可能性があり、正のみが必要です。そして、32 ビットと 64 ビットの両方のプラットフォームで適切に動作するようにしたいと考えています。

つまり、32 ビット Python では、~hash()の範囲の整数を返すことができます。64 ビット システムでは、 ~の範囲の整数を返すことができます。-2**312**31 - 1hash()-2**632**63 - 1

しかし、32 ビット システムではから064ビットシステムでは までの範囲のハッシュが必要です。2**32-102**64-1

32 ビットまたは 64 ビットのターゲット プラットフォームの範囲内で、ハッシュ値を同等の正の値に変換する最善の方法は何ですか?

(コンテキスト:新しいスタイルクラスを作成しようとしています。ドキュメントrandom.Randomによると、シードは「オプションの引数 x は任意のハッシュ可能なオブジェクトにすることができます。」したがって、シードアルゴリズムができないことを除いて、その機能を複製したいと思います負の整数値を処理し、正の値のみを処理します)。random.Random.seed()

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 ではなく `2* n-1 である) で単に使用するのは間違っていますが、修正は非常に簡単です。

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

パフォーマンス上の理由から、sys.maxsize + 1 を 2 つの別々の割り当てに分割して、ほとんどの負の数に対して一時的に長整数を作成しないようにすることができます。私はこれが大した問題になるとは思わないが

于 2013-09-12T14:21:16.043 に答える
1

(編集: 最初は、常に 32 ビット値が必要だと思っていました)

必要なサイズのマスクと単純に AND します。sys.maxsize2 マイナス 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 に答える
1

どうですか:

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

これはsys.maxsize、32 ビット システムと 64 ビット システムの間で移植可能でした。

于 2013-09-12T14:14:40.237 に答える