如何将字符串散列为8位数字?


106

无论如何,我可以将随机字符串散列为8位数字而无需自己实现任何算法吗?


2
hash(“ your string”)%100000000
Theran

2
8位数字似乎很小,如果您有大量记录,则可能导致哈希冲突。stackoverflow.com/questions/1303021/…–
DhruvPathak

使用hashlib,因为hash还有另一个用途!
architectonic

2
任何数量有限的数字都将导致足够数量的散列项发生冲突,这就是为什么您不应该将它们视为唯一键的原因-它倾向于变成生日问题。
亚历克斯·北基

1
我选择“ CityHash”将字符串哈希为19位长的整数(64位整数),希望这将导致比Raymond的建议更少的潜在冲突。en.wikipedia.org/wiki/List_of_hash_functions
tryptofame

Answers:


155

是的,您可以使用内置的hashlib模块或内置的hash函数。然后,对整数形式的哈希使用模运算或字符串切片运算来切掉最后八位数字:

>>> 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
公共服务公告...除了在有限的一组输入值上使用完美散列的特殊情况外,哈希函数不应生成保证的唯一值。
Raymond Hettinger 2015年

5
你读过OP的问题吗?他(或她)想要(或需要)8位小数。同样,哈希表的工作方式是将哈希哈希到一个小的搜索空间(稀疏表)中。您似乎不知道通常需要散列函数,也不关心所提出的实际问题。
Raymond Hettinger 2015年

17
我读了这个问题。我只是观察到,在与SHA-1相同的输入空间上,从天文角度来讲,您的答案更有可能产生碰撞。问题暗含了至少某种程度的唯一性,但是您的答案是一个散列函数,其实质与为每个输入简单返回12345678的精神相同。使用这种方法,我能够用最少1000个输入通过实验产生一次碰撞。为了保持与SHA-1相同的碰撞概率,您必须将未截断的SHA-1映射到8位整数。我认为这值得PSA
twneale 2015年

20
小心,不能保证哈希在平台和运行之间给出相同的结果。
纳皮克先生

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起,此答案有一个非常重要的警告,为防止tar-pitting Python 3.3及更高版本在启动时使用随机哈希种子。
Wolph '18年

如果数字不是您的主要要求,您也可以使用hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]女巫,但还是会发生冲突
lony

他们应该把它放在盒子上!
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));

您正在分享有关python的问题的nodejs解决方案?
Harabeck

是的,当我们构建系统时-后端使用python处理此问题,而前端使用node.js。需要确保两者都能无缝工作。
用户923227
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.