문자열을 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.