Як хешувати рядок на 8 цифр?


106

Чи є в будь-якому випадку, що я можу хешувати випадковий рядок у 8-значне число, не реалізуючи ніяких алгоритмів сам?


2
хеш ("ваш рядок")% 100000000
Теран

2
8 цифр здається малим, і це може призвести до зіткнень хешів, якщо у вас велика кількість записів. stackoverflow.com/questions/1303021 / ...
DhruvPathak

Використовуйте hashlib, оскільки хеш має іншу мету!
архітектоніка

2
Будь-яка кінцева кількість цифр призведе до зіткнень достатньо великої кількості хеш-елементів, тому не слід розглядати їх як унікальні ключі - це, як правило, перетворюється на проблему дня народження.
Алекс Норт-Кіз,

1
Я вибрав "CityHash" для хешування рядків до 19-значних цілих чисел (64-бітові цілі числа), сподіваючись, що це призведе до менших потенційних зіткнень, ніж пропозиція Реймонда нижче. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

Відповіді:


155

Так, ви можете використовувати вбудовані модулі hashlib або вбудовану хеш- функцію. Потім відріжте останні вісім цифр за допомогою модульних операцій або операцій нарізки рядків у цілочисельній формі хешу:

>>> 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
оголошення про публічну службу ... за винятком особливого випадку ідеальних хешей над обмеженим набором вхідних значень, хеш-функції не повинні створювати гарантовані унікальні значення.
Реймонд Хеттінгер,

5
Ви читали запитання ОП? Він (або вона) хотів (або потрібні) 8 знаків після коми. Крім того, спосіб роботи хеш-таблиць полягає у переміщенні в невеликий простір пошуку (розріджена таблиця). Здається, ви не знаєте, для чого зазвичай використовуються хеш-функції, і вас не хвилює фактичне запитання, яке було задано.
Реймонд Хеттінгер

17
Я прочитав питання. Я просто зауважую, що в тому самому вхідному просторі, що і SHA-1, ваша відповідь астрономічно частіше спричиняє зіткнення, ніж ні. Принаймні запитання неявно вимагає певної ступеня унікальності, але ваша відповідь - це хеш-функція в тому ж дусі, що і така, яка просто повертає 12345678 за кожен вхід. За допомогою цього методу мені вдалося експериментально створити зіткнення лише з 1000 входів. Щоб зберегти ту ж ймовірність зіткнення, що і SHA-1, вам доведеться зіставити неврізані SHA-1 на 8-значні цілі числа. Я думаю, що це гідно PSA
twneale

20
Обережно, хеш-сайти не гарантовано давати однакові результати на платформах і пробігах.
Містер Напік,

94

Відповідь Раймонда чудово підходить для 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(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 і вище, використовувати випадкове насіння хешу при запуску.
Wolph

Якщо цифри не є вашою основною вимогою, ви також можете використовувати hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]відьму, яка все одно матиме зіткнення
самотній

Вони повинні покласти це на коробку!
Томаш

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

Я ділюсь нашою реалізацією 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?
Харабек

Так, коли ми будували систему - бекенд обробляв це за допомогою python, тоді як інтерфейс використовував node.js. Потрібно, щоб обидва працювали безперебійно.
користувач 923227
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.