วิธีแฮชสตริงเป็น 8 หลัก?


117

อย่างไรก็ตามฉันสามารถแฮชสตริงแบบสุ่มเป็นตัวเลข 8 หลักโดยไม่ต้องใช้อัลกอริทึมใด ๆ ด้วยตัวเองได้หรือไม่?


3
แฮช ("สตริงของคุณ")% 100000000
Theran

2
ตัวเลข 8 หลักดูเหมือนจะเล็กและอาจส่งผลให้แฮชชนกันหากคุณมีบันทึกจำนวนมาก stackoverflow.com/questions/1303021/…
DhruvPathak

ใช้แฮชลิบเนื่องจากแฮชมีจุดประสงค์อื่น!
สถาปัตยกรรม

3
จำนวนหลักที่ จำกัด จะทำให้เกิดการชนกันของรายการแฮชจำนวนมากพอสมควรนั่นเป็นเหตุผลที่คุณไม่ควรถือว่าพวกเขาเป็นคีย์ที่ไม่ซ้ำกันซึ่งมีแนวโน้มที่จะทำให้เกิดปัญหาในวันเกิด
Alex North-Keys

1
ฉันเลือก "CityHash" เพื่อแฮชสตริงเป็นจำนวนเต็มยาว 19 หลัก (จำนวนเต็ม 64 บิต) โดยหวังว่าจะทำให้เกิดการชนกันน้อยกว่าคำแนะนำของ Raymond ด้านล่าง en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

คำตอบ:


164

ได้คุณสามารถใช้hashlibโมดูลในตัวหรือhashฟังก์ชันในตัว จากนั้นสับเลขแปดหลักสุดท้ายโดยใช้การดำเนินการแบบโมดูโลหรือการตัดสตริงในรูปแบบจำนวนเต็มของแฮช:

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

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

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

30
การประกาศบริการสาธารณะ ... เทคนิคนี้ไม่ได้ส่งผลให้มีค่าแฮชเฉพาะสำหรับสตริง มันคำนวณแฮชแล้วรวมเป็นค่าที่ไม่ซ้ำกันที่ไม่รับประกัน
58

92
ประกาศบริการสาธารณะ ... ยกเว้นกรณีพิเศษของแฮชที่สมบูรณ์แบบเหนือชุดค่าอินพุตที่ จำกัด ฟังก์ชันแฮชไม่ควรสร้างค่าเฉพาะที่รับประกัน
Raymond Hettinger

6
คุณอ่านคำถามของ OP หรือไม่? เขา (หรือเธอ) ต้องการ (หรือต้องการ) ทศนิยม 8 ตำแหน่ง นอกจากนี้วิธีการทำงานของตารางแฮชคือการแฮชลงในพื้นที่ค้นหาขนาดเล็ก (ตารางกระจัดกระจาย) ดูเหมือนคุณจะไม่ทราบว่าต้องการให้มีการใช้ฟังก์ชันแฮชโดยทั่วไปและไม่สนใจคำถามจริงที่ถูกถาม
Raymond Hettinger

18
ฉันอ่านคำถามแล้ว ฉันเพียงแค่สังเกตว่าในพื้นที่อินพุตเดียวกันกับ SHA-1 คำตอบของคุณมีแนวโน้มที่จะก่อให้เกิดการชนกันทางดาราศาสตร์มากกว่าไม่ คำถามนั้นจำเป็นต้องมีความเป็นเอกลักษณ์อย่างน้อยระดับหนึ่งโดยปริยาย แต่คำตอบของคุณคือฟังก์ชันแฮชในจิตวิญญาณเดียวกับที่ส่งคืน 12345678 สำหรับทุกอินพุต ฉันสามารถทดลองสร้างความขัดแย้งกับอินพุตได้มากถึง 1,000 อินพุตโดยใช้วิธีนี้ เพื่อรักษาความน่าจะเป็นในการชนกันของ SHA-1 คุณจะต้องแมป SHA-1 ที่ไม่ได้ตัดทอนเป็นจำนวนเต็ม 8 หลัก ฉันคิดว่ามันคุ้มค่ากับ PSA
twneale

20
แฮชอย่างระมัดระวังไม่ได้รับการรับประกันเพื่อให้ได้ผลลัพธ์ที่เหมือนกันในแพลตฟอร์มและการทำงาน
Mr. Napik

100

คำตอบของ Raymond นั้นยอดเยี่ยมสำหรับ python2 (แม้ว่าคุณจะไม่ต้องการ abs () หรือ parens ประมาณ 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

ดังนั้นขึ้นอยู่กับว่าสิ่งนี้มีความสำคัญในแอปพลิเคชันของคุณหรือไม่ (มันเกิดขึ้นกับฉัน) คุณอาจต้องการยึดแนวทางที่ใช้แฮชลิบ


2
ควรสังเกตว่าคำตอบนี้มีข้อแม้ที่สำคัญมากตั้งแต่ Python 3.3 เพื่อป้องกันไม่ให้ Python 3.3 ขึ้นไปใช้ tar-pitting Python ให้ใช้เมล็ดแฮชแบบสุ่มเมื่อเริ่มต้น
Wolph

หากตัวเลขไม่ใช่ข้อกำหนดหลักของคุณคุณสามารถใช้hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]แม่มดได้ก็ยังจะมีการชนกัน
lony

พวกเขาควรวางไว้บนกล่อง!
Tomasz

4

เพียงเพื่อตอบ 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

ฉันกำลังแบ่งปันการใช้งาน nodejs ของเราในการแก้ปัญหาที่ดำเนินการโดย @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));

คุณกำลังแชร์โซลูชัน nodejs ในคำถามเกี่ยวกับ python หรือไม่?
Harabeck

ใช่ตอนที่เราสร้างระบบแบ็กเอนด์ประมวลผลโดยใช้ python ในขณะที่ frontend ใช้ node.js จำเป็นเพื่อให้แน่ใจว่าทั้งสองอย่างทำงานได้อย่างราบรื่น
ผู้ใช้ 923227
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.