Bagaimana cara membagi string menjadi 8 digit?

107

Apakah ada yang bisa saya hash string acak menjadi angka 8 digit tanpa menerapkan algoritma sendiri?

dorafmon.dll
sumber
2
hash ("string Anda")% 100000000
Theran
2
8 digit tampaknya kecil, dan dapat mengakibatkan benturan hash jika Anda memiliki banyak record. stackoverflow.com/questions/1303021/…
DhruvPathak
Gunakan hashlib karena hash memiliki tujuan lain!
arsitektonis
2
Jumlah digit yang terbatas akan mengakibatkan tabrakan untuk sejumlah besar item hash, itulah mengapa Anda tidak boleh memperlakukannya sebagai kunci unik - ini cenderung berubah menjadi masalah ulang tahun.
Alex North-Keys
1
Saya telah memilih "CityHash" untuk mem-hash string menjadi 19 digit integer panjang (64bit integers), berharap ini akan menyebabkan potensi tabrakan yang lebih sedikit daripada saran Raymond di bawah ini. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

Jawaban:

157

Ya, Anda dapat menggunakan modul hashlib built-in atau fungsi hash built-in . Kemudian, potong delapan digit terakhir menggunakan operasi modulo atau operasi pemotongan string pada bentuk integer dari hash:

>>> 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
Raymond Hettinger
sumber
27
pengumuman layanan publik ... teknik ini sebenarnya tidak menghasilkan nilai hash unik untuk string; itu menghitung hash dan kemudian memungut menjadi nilai unik yang tidak dijamin
twneale
89
pengumuman layanan publik ... kecuali untuk kasus khusus dari hash sempurna atas kumpulan nilai input yang terbatas, fungsi hash tidak seharusnya menghasilkan nilai unik yang dijamin.
Raymond Hettinger
5
Apakah Anda membaca pertanyaan OP? Dia (atau dia) ingin (atau membutuhkan) 8 tempat desimal. Juga, cara kerja tabel hash adalah dengan melakukan hash ke dalam ruang pencarian kecil (tabel jarang). Anda sepertinya tidak tahu fungsi hash yang diinginkan biasanya digunakan untuk dan tidak peduli dengan pertanyaan sebenarnya yang ditanyakan.
Raymond Hettinger
17
Saya membaca pertanyaannya. Saya hanya mengamati bahwa pada ruang input yang sama dengan SHA-1, jawaban Anda secara astronomis lebih mungkin menghasilkan tabrakan daripada tidak. Setidaknya beberapa derajat keunikan secara implisit diperlukan oleh pertanyaan, tetapi jawaban Anda adalah fungsi hash dengan semangat yang sama seperti yang hanya mengembalikan 12345678 untuk setiap masukan. Saya dapat secara eksperimental menghasilkan tabrakan dengan sedikitnya 1000 input menggunakan metode ini. Untuk mempertahankan probabilitas tabrakan yang sama seperti SHA-1, Anda harus memetakan SHA-1 yang tidak terpotong ke bilangan bulat 8 digit. Saya pikir itu layak untuk PSA
twneale
20
Hati-hati, hash tidak dijamin untuk memberikan hasil yang sama di seluruh platform dan berjalan.
Tn. Napik
95

Jawaban Raymond sangat bagus untuk python2 (meskipun, Anda tidak memerlukan abs () atau parens sekitar 10 ** 8). Namun, untuk python3, ada peringatan penting. Pertama, Anda harus memastikan bahwa Anda meneruskan string yang dienkode. Hari-hari ini, dalam banyak situasi, mungkin juga lebih baik untuk menghindar dari sha-1 dan menggunakan sesuatu seperti sha-256. Jadi, pendekatan hashlib adalah:

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

Jika Anda ingin menggunakan fungsi hash (), peringatan pentingnya adalah, tidak seperti di Python 2.x, di Python 3.x, hasil hash () hanya akan konsisten dalam suatu proses, bukan di seluruh pemanggilan python. Lihat disini:

$ 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

Ini berarti solusi berbasis hash () disarankan, yang dapat disingkat menjadi hanya:

hash(s) % 10**8

hanya akan mengembalikan nilai yang sama dalam menjalankan skrip tertentu:

#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

Jadi, tergantung pada apakah ini penting dalam aplikasi Anda (itu terjadi di aplikasi saya), Anda mungkin ingin tetap menggunakan pendekatan berbasis hashlib.

JJC
sumber
2
Perlu dicatat bahwa jawaban ini memiliki peringatan yang sangat penting karena Python 3.3, untuk melindungi dari tar-pitting Python 3.3 dan yang lebih tinggi gunakan hash seed acak saat startup.
Wolph
Jika angka bukan persyaratan utama Anda, Anda juga bisa menggunakan hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]penyihir yang masih akan bertabrakan
lony
Mereka harus menaruhnya di kotak!
Tomasz
3

Sekadar melengkapi jawaban JJC, di python 3.5.3 perilakunya sudah benar jika menggunakan hashlib seperti ini:

$ 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
pengguna8948052
sumber
-3

Saya membagikan implementasi nodejs kami dari solusi seperti yang diterapkan oleh @Raymond Hettinger.

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));
pengguna 923227
sumber
Anda berbagi solusi nodejs dalam pertanyaan tentang python?
Harabeck
Ya, saat kita membangun sistem - backend memproses ini menggunakan python sedangkan frontend menggunakan node.js. Diperlukan untuk memastikan keduanya bekerja dengan lancar.
pengguna 923227