Last active
February 13, 2025 03:48
-
-
Save eplawless/52813b1d8ad9af510d85 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function hash(str) { | |
var len = str.length; | |
var hash = 5381; | |
for (var idx = 0; idx < len; ++idx) { | |
hash = 33 * hash + str.charCodeAt(idx); | |
} | |
return hash; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just want to point out this is not reliable in JS due to numbers being 53-bit floats not 32-bit ints where overflow can be relied on instead of losing precision.
Your
hash = 33 * hash + str.charCodeAt(idx)
will result inhash("hello")
return value of2osu1y1l
(viaresult.toString(36)
, base36 is the highest radix supported via this method, charset is0-9a-v
)If you use another variant that does bitshift arithmetic for multiplication,
hash = (hash << 5) + hash) + str.charCodeAt(idx)
, you'll get:4bj995
. To get the same value from your method, instead ofreturn hash
, usereturn hash >>> 0
, this will convert to a 32-bit positive number(uint
instead ofint
). This doesn't help with long enough inputs however as the number in the loop is not kept at/near 32-bit, if the iterations is long enough, you can end up withInfinity
..You'll still want to use
return hash >>> 0
with the bitshift arithmetic version too, as once the hash value in the loop exceeds 32-bits, you'll have similar problems. The reason is that the bitshift will keep it within the 32-bit range as bitwise operators in JS work on 32-bits, however, addition follows right after it and that can push the number over 32-bit range..There is an improved variant of
djb2
that uses XOR(^
) which as another bitwise operator will keep the JS value within the 32-bit range, it does not have the equivalent effect of addition however, so results will not match prior approaches, for"hello"
, this time you'll get a base36 value of"2y0dev"
.TL;DR: Here's what you want to use in JS:
Using
h * 33
here is ok now, since the final operator^
is truncating each iteration to 32-bits. The following should help validate that: