Six hash functions, each fixing one flaw of the one before. Every row shows the 32 bits of h after one operation, so you can watch how much each character actually scrambles it.
h % 32 keeps
| Stage | Order matters | Every character counts | Change spreads to high bits |
|---|---|---|---|
| 1 · sum | no | yes | no |
| 2 · OR | no | no, bits saturate | no |
| 3 · XOR | no | yes | no |
| 4 · XOR, × 256 | yes | last 3 only | no, just shifted |
| 5 · FNV-1 | yes | yes | not for the last character |
| 6 · FNV-1a | yes | yes | yes |
h % 32 actually seesMultiplication only carries changes upward: bit k of the input can change bits k and above, never below. XOR doesn't move bits at all. So in both FNV versions, the lowest 5 bits of h depend only on the lowest 5 bits of each character. 'b' (0x62) and 'B' (0x42) differ only in bit 5, so they always land in the same slot. Click aB above: many bits differ, but the slots are equal.
The fix is to fold the high bits down before taking the remainder, for example (h ^ (h >> 16)) % 32, or to use a table size that isn't a power of two, like 31, so % depends on every bit.