Bir dizeyi 8 basamağa nasıl hash edebilirim?


109

Kendim herhangi bir algoritma uygulamadan rastgele bir dizeyi 8 basamaklı bir sayıya hash edebilir miyim?


2
karma ("
dizeniz

2
8 basamak küçük görünür ve çok sayıda kaydınız varsa karma çakışmalara neden olabilir. stackoverflow.com/questions/1303021/…
DhruvPathak

Hashlib kullanmanın başka bir amacı vardır!
arkitektonik

2
Herhangi bir sonlu rakam, yeterince büyük sayıdaki karma öğe için çarpışmalara neden olacaktır, bu yüzden onları benzersiz anahtarlar olarak değerlendirmemelisiniz - bu, doğum günü sorununa dönüşme eğilimindedir.
Alex North-Keys

1
Dizeleri 19 basamaklı uzun tam sayılara (64 bit tam sayılar) hash etmek için "CityHash" ı seçtim, bunun Raymond'un aşağıdaki önerisinden daha az olası çarpışmaya yol açacağını umuyorum. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

Yanıtlar:


160

Evet, yerleşik hashlib modüllerini veya yerleşik hash işlevini kullanabilirsiniz. Ardından, hash'in tamsayı biçiminde modulo işlemlerini veya dize dilimleme işlemlerini kullanarak son sekiz basamağı kesin:

>>> 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

30
kamu hizmeti duyurusu ... bu teknik aslında dizge için benzersiz bir karma değerle sonuçlanmaz; bir hash hesaplar ve sonra garanti edilmeyen benzersiz bir değere
dönüşür

90
kamu hizmeti duyurusu ... sınırlı girdi değerleri kümesindeki mükemmel karmaşaların özel durumu dışında, karma işlevlerin garantili benzersiz değerler üretmesi beklenmez.
Raymond Hettinger

5
OP'nin sorusunu okudunuz mu? 8 ondalık basamak istedi (veya gerekli). Ayrıca, karma tabloların çalışma şekli, küçük bir arama alanına (seyrek tablo) karma yapmaktır. Görünüşe göre, istek hash işlevlerinin yaygın olarak kullanıldığını ve sorulan asıl soruyu umursamadığını bilmiyorsunuz.
Raymond Hettinger

18
Soruyu okudum. Sadece SHA-1 ile aynı girdi uzayında, cevabınızın astronomik olarak bir çarpışma yaratma olasılığının, olmamasından daha yüksek olduğunu gözlemliyorum. Soru, en azından bir dereceye kadar benzersizlik gerektiriyor, ancak cevabınız, her girdi için basitçe 12345678 döndüren bir karma işlevdir. Bu yöntemi kullanarak deneysel olarak 1000 girdiyle bir çarpışma oluşturabildim. SHA-1 ile aynı çarpışma olasılığını korumak için, kesilmemiş SHA-1'leri 8 basamaklı tam sayılarla eşlemeniz gerekir. Bence bu bir PSA'ya layık
twneale

20
Dikkatli olun, hash (ler), platformlar ve çalıştırmalar arasında aynı sonuçları verecek şekilde garanti edilmez.
Bay Napik

99

Raymond'ın cevabı python2 için harika (yine de abs () ya da 10 ** 8 civarında parenlere ihtiyacınız yok). Bununla birlikte, python3 için önemli uyarılar vardır. Öncelikle, kodlanmış bir dizeyi ilettiğinizden emin olmanız gerekir. Bugünlerde çoğu durumda sha-1'den uzak durmak ve bunun yerine sha-256 gibi bir şey kullanmak muhtemelen daha iyidir. Dolayısıyla, hashlib yaklaşımı şöyle olacaktır:

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

Bunun yerine hash () işlevini kullanmak istiyorsanız, önemli uyarı, Python 2.x'in aksine, Python 3.x'te, hash () sonucunun python çağrılarında değil, yalnızca bir işlem içinde tutarlı olacağıdır. Buraya bakın:

$ 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

Bu, önerilen hash () tabanlı çözüm anlamına gelir ve şu şekilde kısaltılabilir:

hash(s) % 10**8

yalnızca belirli bir komut dosyası çalıştırmasında aynı değeri döndürür:

#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

Bu nedenle, uygulamanızda bunun önemli olup olmadığına bağlı olarak (benimkinde de vardı), muhtemelen hashlib tabanlı yaklaşıma bağlı kalmak isteyeceksiniz.


2
Bu cevabın Python 3.3'ten beri çok önemli bir uyarısı olduğu unutulmamalıdır, Python 3.3 ve üzeri zift çukurlarına karşı koruma sağlamak için başlangıçta rastgele bir hash tohum kullanın.
Wolph

Rakamlar ana gereksiniminiz değilse, hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]cadı da kullanabilirsiniz, yine de çarpışmalar
yaşayabilirsiniz

Bunu kutuya koymalılar!
Tomasz

3

Sadece JJC cevabını tamamlamak için, python 3.5.3'te hashlib'i bu şekilde kullanırsanız davranış doğrudur:

$ 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 tarafından uygulanan çözümün nodejs uygulamasını paylaşıyorum.

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 ile ilgili bir soruda bir nodejs çözümünü paylaşıyorsunuz?
Harabeck

Evet, sistemi oluştururken arka uç bunu python kullanarak işlerken ön uç node.js kullanırken Her ikisinin de sorunsuz çalıştığından emin olmak gerekiyordu.
kullanıcı 923227
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.