I'm trying to learn how to do some basic hashing in Javascript and I've e across the following algorithm:
var hash = 0;
for (i = 0; i < this.length; i++) {
char = str.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash;
}
I don't really understand how it works and I was hoping you could help me out. In particular I don't understand (hash<<5)-hash
and hash = hash & hash
. Thank you for your replies.
Note: For anyone looking for the source, it's an implementation of Java’s String.hashCode():
I'm trying to learn how to do some basic hashing in Javascript and I've e across the following algorithm:
var hash = 0;
for (i = 0; i < this.length; i++) {
char = str.charCodeAt(i);
hash = ((hash<<5)-hash)+char;
hash = hash & hash;
}
I don't really understand how it works and I was hoping you could help me out. In particular I don't understand (hash<<5)-hash
and hash = hash & hash
. Thank you for your replies.
Note: For anyone looking for the source, it's an implementation of Java’s String.hashCode(): http://werxltd./wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method
Share Improve this question edited Sep 25, 2017 at 5:25 Lucas Astrada 521 silver badge6 bronze badges asked Sep 14, 2013 at 15:50 Tenescu AndreiTenescu Andrei 3352 gold badges5 silver badges15 bronze badges 3-
Where did you find that code? I don't think it's very good as an example. In particular, the
hash = hash & hash
step looks superfluous. It may be there to keep the value in the integer range, I suppose. – Pointy Commented Sep 14, 2013 at 15:52 - I don't remember exactly. I was searching on Google and this came up. I recently though about it and since I didn't really understood how it worked, I posted it here. – Tenescu Andrei Commented Sep 14, 2013 at 17:58
- Can you put up a better example. – user3376708 Commented Jul 13, 2014 at 20:04
5 Answers
Reset to default 3The step
hash = ((hash << 5) - hash) + char;
is effectively:
hash = ((hash * 32) - hash) + char;
Then,
hash = hash & hash;
will only change the value if the number has overflowed the integer range (32 bits, or maybe 31). (I wouldn't do it that way but it's a matter of style.)
In that code, the variables "i" and "char" should be declared:
var hash = 0, i, char;
<< and & are bitwise operations. One is shifting bits and the other is anding them.
0010 << 2
bees 1000
because everything is shifted to the left.
0101 & 1110
bees 0100
because the result is 1 whenever both values have 1's for that particular bit.
@Pointy's answer explains what the hash = hash & hash
(& the same value) acplishes, I wasn't sure what it did.
See:
https://en.wikipedia/wiki/Bitwise_operation https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators
A mon technique for hashing is to start with 0. Then you multiply the existing hash value by a prime number, and finally add the new element to it.
In this case:
((hash << 5) - hash)
is effectively "hash * 31". Apply the left shift operator, <<
, 5 times is like multiplying the number by 2, 5 times. Or, multiplying it by 2^5, which is 32. Then they subtract once, giving 31.
The hash & hash
is effectively a "do nothing" operation, performing a logical AND (&
) on a number with itself returns the same number, it doesn't "do anything", but it may be used to coerce the number and make sure it remains an integer. There's likely some JS machinations going on with the representation of the number and that's what the second line is for.
If this was just raw C, it would simply be hash = hash * 31 + char
.
hash << 5
is bitshifting the value of hash to the "left" 5 places. This is equivalent to hash * 32
. For a hash-generation algorithm, it's easier to think of it in terms of moving the bits.
hash = hash & hash
looks like a mistake. It "ands" the value of hash with itself and assigns it back to itself. Anding the value with itself results in the original value, so it's a form of nop.
The << represents the left shift operation. This operator shifts the first operand the specified number of bits to the left, for example:
var num = 2; // in binary 10
var shift = 2 << 2; //shift is 8, in binary 1000
The & operator represents an AND logical operation, for example:
var num1 = 6; // in binary 110
var num2 = 7; // in binary 111
var result = num1 & num2; // result is 6, in binary 110
for a plete reference on bitwise operators take a look on the Mozilla javascript reference.