文字列を8桁にハッシュする方法は?


106

とにかく自分でアルゴリズムを実装せずにランダムな文字列を8桁の数値にハッシュできるのですか?


2
hash( "your string")%100000000
Theran

2
8桁は小さいようですが、レコード数が多い場合はハッシュの衝突が発生する可能性があります。stackoverflow.com/questions/1303021/...
DhruvPathak

ハッシュには別の目的があるので、hashlibを使用してください!
建築家

2
桁数に制限があると、ハッシュアイテムの数が十分に多い場合に競合が発生します。そのため、それらを一意のキーとして扱わないでください。誕生日の問題になりがちです。
Alex North-Keys

1
文字列を19桁の長整数(64ビット整数)にハッシュするために "CityHash"を選択しました。これにより、レイモンドの提案よりも衝突の可能性が少なくなることを期待しています。en.wikipedia.org/wiki/List_of_hash_functions
tryptofame 2017

回答:


154

はい、組み込みのhashlibモジュールまたは組み込みのハッシュ関数を使用できます。次に、ハッシュの整数形式でモジュロ演算または文字列スライス演算を使用して、最後の8桁を切り捨てます。

>>> s = 'she sells sea shells by the sea shore'

>>> # Use hashlib
>>> import hashlib
>>> int(hashlib.sha1(s).hexdigest(), 16) % (10 ** 8)
58097614L

>>> # Use hash()
>>> abs(hash(s)) % (10 ** 8)
82148974

26
公共サービスの告知...この手法では、実際には文字列の一意のハッシュ値は得られません。ハッシュを計算し、保証されていない一意の値に変更します
twneale

88
公共サービスの発表...入力値の制限されたセットに対する完全なハッシュの特別な場合を除いて、ハッシュ関数は保証された一意の値を生成することは想定されていません。
レイモンドヘッティンガー2015

5
OPの質問を読みましたか?彼(または彼女)は小数点以下8桁を望んでいました(または必要としました)。また、ハッシュテーブルが機能する方法は、小さなサーチスペース(スパーステーブル)にハッシュすることです。あなたはハッシュ関数が一般的に使われることを望んでいないようで、尋ねられた実際の質問を気にしません。
レイモンドヘッティンガー2015

17
質問を読みました。私は単にSHA-1と同じ入力空間で、あなたの答えは天文学的に衝突よりも発生する可能性が高いことを観察しています。質問には少なくともある程度の一意性が暗黙的に要求されますが、答えはすべての入力に対して単純に12345678を返すものと同じ精神のハッシュ関数です。この方法を使用して、わずか1000入力の衝突を実験的に生成することができました。SHA-1と同じ衝突確率を維持するには、切り捨てられていないSHA-1を8桁の整数にマッピングする必要があります。それはPSAに値すると思います
twneale '21

20
ハッシュは、プラットフォームや実行全体で同じ結果が得られるとは保証されていません。
Napik氏2016

94

レイモンドの答えはpython2に最適です(ただし、abs()や10 ** 8前後の括弧は必要ありません)。ただし、python3には重要な注意事項があります。まず、エンコードされた文字列を渡すことを確認する必要があります。最近では、ほとんどの状況で、sha-1を避けて、代わりにsha-256のようなものを使用することをお勧めします。したがって、hashlibアプローチは次のようになります。

>>> import hashlib
>>> s = 'your string'
>>> int(hashlib.sha256(s.encode('utf-8')).hexdigest(), 16) % 10**8
80262417

代わりにhash()関数を使用する場合、重要な注意点は、Python 2.xとは異なり、Python 3.xでは、hash()の結果はプロセス内でのみ一貫し、Pythonの呼び出し全体では一貫しないことです。こちらをご覧ください:

$ python -V
Python 2.7.5
$ python -c 'print(hash("foo"))'
-4177197833195190597
$ python -c 'print(hash("foo"))'
-4177197833195190597

$ python3 -V
Python 3.4.2
$ python3 -c 'print(hash("foo"))'
5790391865899772265
$ python3 -c 'print(hash("foo"))'
-8152690834165248934

これは、hash()ベースのソリューションが提案されていることを意味します。

hash(s) % 10**8

指定されたスクリプト実行内で同じ値のみを返します。

#Python 2:
$ python2 -c 's="your string"; print(hash(s) % 10**8)'
52304543
$ python2 -c 's="your string"; print(hash(s) % 10**8)'
52304543

#Python 3:
$ python3 -c 's="your string"; print(hash(s) % 10**8)'
12954124
$ python3 -c 's="your string"; print(hash(s) % 10**8)'
32065451

したがって、これがアプリケーションで重要かどうかに応じて(私の場合)、hashlibベースのアプローチに固執する必要があります。


2
この答えは、Python 3.3以降、非常に重要な注意事項です。Python3.3以降のタールピットから保護するために、起動時にランダムハッシュシードを使用します。
Wolph 2018年

数字が主な要件でない場合は、hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]魔女を使用することもできます。衝突が発生します
lony

彼らはそれを箱に入れるべきです!
Tomasz

3

JJC回答を完了するために、Python 3.5.3では、hashlibを次のように使用した場合の動作は正しいです。

$ python3 -c '
import hashlib
hash_object = hashlib.sha256(b"Caroline")
hex_dig = hash_object.hexdigest()
print(hex_dig)
'
739061d73d65dcdeb755aa28da4fea16a02b9c99b4c2735f2ebfa016f3e7fded
$ python3 -c '
import hashlib
hash_object = hashlib.sha256(b"Caroline")
hex_dig = hash_object.hexdigest()
print(hex_dig)
'
739061d73d65dcdeb755aa28da4fea16a02b9c99b4c2735f2ebfa016f3e7fded

$ python3 -V
Python 3.5.3

-3

@Raymond Hettingerによって実装されたソリューションのnodejs実装を共有しています。

var crypto = require('crypto');
var s = 'she sells sea shells by the sea shore';
console.log(BigInt('0x' + crypto.createHash('sha1').update(s).digest('hex'))%(10n ** 8n));

あなたはpythonについての質問でnodejsソリューションを共有していますか?
Harabeck

はい、システムを構築しているときに、フロントエンドがnode.jsを使用していたときに、バックエンドがpythonを使用してこれを処理しました。両方がシームレスに機能することを確認する必要がありました。
ユーザー923227
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.