Làm thế nào để băm một chuỗi thành 8 chữ số?


106

Có cách nào mà tôi có thể băm một chuỗi ngẫu nhiên thành một số 8 chữ số mà không cần tự thực hiện bất kỳ thuật toán nào không?


2
băm ("chuỗi của bạn")% 100000000
Theran

2
Chữ số 8 có vẻ nhỏ và có thể dẫn đến xung đột của các hàm băm nếu bạn có số lượng lớn các bản ghi. stackoverflow.com/questions/1303021/…
DhruvPathak

Sử dụng hashlib vì hash có mục đích khác!
Architectonic

2
Bất kỳ số lượng chữ số hữu hạn nào cũng sẽ dẫn đến va chạm cho số lượng đủ lớn các mục băm, đó là lý do tại sao bạn không nên coi chúng như các khóa duy nhất - nó có xu hướng trở thành vấn đề sinh nhật.
Alex North-Keys

1
Tôi đã chọn "CityHash" để băm chuỗi thành số nguyên dài 19 chữ số (số nguyên 64 bit), hy vọng điều này sẽ dẫn đến ít va chạm tiềm ẩn hơn đề xuất của Raymond bên dưới. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

Câu trả lời:


154

Có, bạn có thể sử dụng được xây dựng trong hashlib module hoặc được xây dựng trong hash function. Sau đó, cắt bỏ tám chữ số cuối cùng bằng cách sử dụng các phép toán modulo hoặc phép toán cắt chuỗi trên dạng số nguyên của hàm băm:

>>> 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
thông báo dịch vụ công cộng ... kỹ thuật này không thực sự dẫn đến một giá trị băm duy nhất cho chuỗi; nó tính một băm và sau đó munges thành một giá trị không đảm bảo duy nhất
twneale

88
thông báo dịch vụ công cộng ... ngoại trừ trường hợp đặc biệt của hàm băm hoàn hảo trên tập hợp giá trị đầu vào giới hạn, các hàm băm không được cho là tạo ra các giá trị duy nhất được đảm bảo.
Raymond Hettinger

5
Bạn đã đọc câu hỏi của OP chưa? Anh ấy (hoặc cô ấy) muốn (hoặc cần) 8 chữ số thập phân. Ngoài ra, cách hoạt động của bảng băm là băm vào một không gian tìm kiếm nhỏ (bảng thưa thớt). Bạn dường như không biết muốn các hàm băm thường được sử dụng cho và không quan tâm đến câu hỏi thực tế đã được hỏi.
Raymond Hettinger

17
Tôi đọc câu hỏi. Tôi chỉ đơn giản là quan sát thấy rằng trên cùng một không gian đầu vào như SHA-1, câu trả lời của bạn có nhiều khả năng tạo ra va chạm hơn là không. Ít nhất một số mức độ duy nhất được yêu cầu ngầm bởi câu hỏi, nhưng câu trả lời của bạn là một hàm băm theo tinh thần giống như một hàm đơn giản trả về 12345678 cho mọi đầu vào. Tôi đã có thể thực nghiệm tạo ra xung đột với khoảng 1000 đầu vào bằng phương pháp này. Để bảo toàn xác suất va chạm giống như SHA-1, bạn sẽ phải ánh xạ các SHA-1 chưa được cắt ngắn thành các số nguyên có 8 chữ số. Tôi nghĩ nó xứng đáng với một PSA
twneale

20
Cẩn thận, (các) hàm băm không được phân biệt để đưa ra kết quả giống nhau trên các nền tảng và quá trình chạy.
Ông Napik

94

Câu trả lời của Raymond là rất tốt cho python2 (tuy nhiên, bạn không cần abs () cũng như parens khoảng 10 ** 8). Tuy nhiên, đối với python3, có những lưu ý quan trọng. Trước tiên, bạn cần đảm bảo rằng mình đang chuyển một chuỗi được mã hóa. Ngày nay, trong hầu hết các trường hợp, có lẽ tốt hơn là nên tránh xa sha-1 và thay vào đó sử dụng một thứ gì đó như sha-256. Vì vậy, cách tiếp cận hashlib sẽ là:

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

Nếu bạn muốn sử dụng hàm băm () thay thế, lưu ý quan trọng là, không giống như trong Python 2.x, trong Python 3.x, kết quả của hash () sẽ chỉ nhất quán trong một quy trình, không phải trên các lệnh gọi python. Xem tại đây:

$ 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

Điều này có nghĩa là giải pháp dựa trên hash () được đề xuất, có thể được rút ngắn thành:

hash(s) % 10**8

sẽ chỉ trả về cùng một giá trị trong một lần chạy tập lệnh nhất định:

#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

Vì vậy, tùy thuộc vào việc điều này có quan trọng trong ứng dụng của bạn hay không (nó đã xảy ra trong ứng dụng của tôi), có thể bạn sẽ muốn tiếp cận với phương pháp dựa trên hashlib.


2
Cần lưu ý rằng câu trả lời này có một cảnh báo rất quan trọng kể từ Python 3.3, để bảo vệ chống lại việc rỗ bằng tar Python 3.3 trở lên, hãy sử dụng một hạt băm ngẫu nhiên khi khởi động.
Wolph

Nếu chữ số không phải là yêu cầu chính của bạn, bạn cũng có thể sử dụng hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]phù thủy vẫn sẽ có va chạm
lony

Họ nên đặt nó vào hộp!
Tomasz

3

Chỉ để hoàn thành câu trả lời JJC, trong python 3.5.3, hành vi là chính xác nếu bạn sử dụng hashlib theo cách này:

$ 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

Tôi đang chia sẻ việc triển khai giải pháp nodejs của chúng tôi do @Raymond Hettinger triển khai.

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

Bạn đang chia sẻ giải pháp nodejs trong câu hỏi về python?
Harabeck

Có, khi chúng tôi đang xây dựng hệ thống - phần phụ trợ đã xử lý điều này bằng python trong khi giao diện người dùng sử dụng node.js. Cần thiết để đảm bảo cả hai hoạt động liền mạch.
người dùng 923227
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.