문자열을 8 자리로 해시하는 방법은 무엇입니까?


106

어쨌든 알고리즘을 직접 구현하지 않고 임의의 문자열을 8 자리 숫자로 해시 할 수 있습니까?


2
해시 ( "당신의 문자열") % 100,000,000
Theran

2
8 자리 숫자가 작게 보이며 레코드 수가 많으면 해시 충돌이 발생할 수 있습니다. stackoverflow.com/questions/1303021/...
DhruvPathak

해시는 또 다른 목적이 있으므로 hashlib를 사용하십시오!
architectonic

2
한정된 숫자의 숫자는 충분히 많은 수의 해시 항목에 대해 충돌을 유발하므로 고유 키로 취급해서는 안됩니다. 생일 문제로 바뀌는 경향이 있습니다.
Alex North-Keys

1
문자열을 19 자리 정수 (64 비트 정수)로 해시하기 위해 "CityHash"를 선택했습니다. 이것이 아래의 Raymond 제안보다 잠재적 충돌이 적기를 바랍니다. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

답변:


155

예, 기본 제공 hashlib 모듈 또는 기본 제공 해시 함수를 사용할 수 있습니다. 그런 다음 해시의 정수 형식에서 모듈로 연산 또는 문자열 슬라이싱 연산을 사용하여 마지막 8 자리를 잘라냅니다.

>>> 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
공익 광고 ...이 기술은 실제로 문자열에 대해 고유 한 해시 값을 생성하지 않습니다. 해시를 계산 한 다음 보장되지 않는 고유 값으로
뭉칩니다.

88
공익 광고 ... 제한된 입력 값 세트에 대한 완벽한 해시의 특별한 경우를 제외하고 해시 함수는 보장 된 고유 값을 생성하도록되어 있지 않습니다.
Raymond Hettinger 2015 년

5
OP의 질문을 읽었습니까? 그 (또는 그녀)는 소수점 8 자리를 원했습니다 (또는 필요했습니다). 또한 해시 테이블이 작동하는 방식은 작은 검색 공간 (희소 테이블)으로 해시하는 것입니다. 해시 함수가 일반적으로 사용되는 것을 원하는지 모르고 실제 질문에 대해 신경 쓰지 않는 것 같습니다.
Raymond Hettinger 2015 년

17
나는 질문을 읽었다. 나는 단순히 SHA-1과 동일한 입력 공간에서 귀하의 대답이 천문학적으로 충돌을 일으킬 가능성이 더 높다는 것을 관찰하고 있습니다. 질문에 암시 적으로 어느 정도의 고유성이 필요하지만 귀하의 대답은 모든 입력에 대해 12345678을 단순히 반환하는 것과 동일한 정신의 해시 함수입니다. 이 방법을 사용하여 실험적으로 1000 개 정도의 입력으로 충돌을 생성 할 수있었습니다. SHA-1과 동일한 충돌 확률을 유지하려면 잘리지 않은 SHA-1을 8 자리 정수로 매핑해야합니다. PSA의 가치가 있다고 생각합니다
twneale

20
조심스럽게 해시는 플랫폼과 실행간에 동일한 결과를 제공하도록 보장되지 않습니다.
Mr. Napik

94

Raymond의 대답은 python2에 적합합니다 (그러나 abs () 또는 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

따라서 이것이 귀하의 응용 프로그램에서 중요한지 여부에 따라 (내게 그랬습니다) hashlib 기반 접근 방식을 고수하고 싶을 것입니다.


2
이 답변은 Python 3.3 이후로 타르 피팅을 방지하기 위해 Python 3.3 이상에서 시작시 임의의 해시 시드를 사용하는 것을 방지하기 위해 매우 중요한 경고가 있음을 유의해야합니다.
Wolph

숫자가 주요 요구 사항이 아닌 경우 hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]마녀 를 사용할 수도 있습니다. 여전히 충돌이 발생합니다
lony dec

상자에 넣어야합니다!
Tomasz

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

@Raymond Hettinger가 구현 한 솔루션의 nodejs 구현을 공유하고 있습니다.

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 솔루션을 공유하고 있습니까?
Harabeck

예, 시스템을 구축 할 때 백엔드는 파이썬을 사용하여 처리했고 프런트 엔드는 node.js를 사용했습니다. 둘 다 원활하게 작동하는지 확인해야합니다.
사용자 923227
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.