Skip to content

Instantly share code, notes, and snippets.

@amakukha
Forked from mengzhuo/hash_djb2.py
Last active March 19, 2023 08:55
Show Gist options
  • Save amakukha/7854a3e910cb5866b53bf4b2af1af968 to your computer and use it in GitHub Desktop.
Save amakukha/7854a3e910cb5866b53bf4b2af1af968 to your computer and use it in GitHub Desktop.
DJB2 Hash in Python
# Proper (fast) Python implementations of Dan Bernstein's DJB2 32-bit hashing function
#
# DJB2 has terrible avalanching performance, though.
# For example, it returns the same hash values for these strings: "xy", "yX", "z7".
# I recommend using Murmur3 hash. Or, at least, FNV-1a or SDBM hashes below.
import functools
djb2 = lambda x: functools.reduce(lambda x,c: 0xFFFFFFFF & (x*33 + c), x, 5381)
sdbm = lambda x: functools.reduce(lambda x,c: 0xFFFFFFFF & (x*65599 + c), x, 0)
fnv1a_32 = lambda x: functools.reduce(lambda x,c: 0xFFFFFFFF & ((x^c)*0x1000193), x, 0x811c9dc5)
hex(djb2(b'hello, world')) == '0xb0e4250d'
hex(sdbm(b'hello, world')) == '0xee6fb30c'
hex(fnv1a_32(b'hello, world')) == '0x4d0ea41d'
# ...Versions for strings with regular functions
def hash_djb2(s):
hash = 5381
for x in s:
hash = ((( hash << 5) + hash) + ord(x)) & 0xFFFFFFFF
return hash
def hash_sdbm(s):
hash = 0
for x in s:
hash = ((hash << 16) + (hash << 6) + ord(x) - hash) & 0xFFFFFFFF
return hash
def hash_fnv1a_32(s):
hash = 0x811c9dc5
for x in s:
hash = ((ord(x) ^ hash) * 0x01000193) & 0xFFFFFFFF
return hash
hex(hash_djb2(u'hello world, 世界')) == '0xa6bd702f'
hex(hash_sdbm(u'Åland Islands')) == '0x5f5ba0ee'
hex(hash_fnv1a_32(u'Świętosław')) == '0x16cf4524'
@metala
Copy link

metala commented Nov 5, 2021

You don't need itertools.chain, since you have optional initial value in functools.reduce.

djb2 = lambda x: functools.reduce(lambda x,c: (x*33 + ord(c)) & 0xFFFFFFFF, x, 5381)

@amakukha
Copy link
Author

amakukha commented Nov 5, 2021

Thanks! Noted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment