What integer hash function are good that accepts an integer hash key?

前端 未结 11 1600
孤街浪徒
孤街浪徒 2020-11-22 17:23

What integer hash function are good that accepts an integer hash key?

相关标签:
11条回答
  • 2020-11-22 17:57

    I found the following algorithm provides a very good statistical distribution. Each input bit affects each output bit with about 50% probability. There are no collisions (each input results in a different output). The algorithm is fast except if the CPU doesn't have a built-in integer multiplication unit. C code, assuming int is 32 bit (for Java, replace >> with >>> and remove unsigned):

    unsigned int hash(unsigned int x) {
        x = ((x >> 16) ^ x) * 0x45d9f3b;
        x = ((x >> 16) ^ x) * 0x45d9f3b;
        x = (x >> 16) ^ x;
        return x;
    }
    

    The magic number was calculated using a special multi-threaded test program that ran for many hours, which calculates the avalanche effect (the number of output bits that change if a single input bit is changed; should be nearly 16 on average), independence of output bit changes (output bits should not depend on each other), and the probability of a change in each output bit if any input bit is changed. The calculated values are better than the 32-bit finalizer used by MurmurHash, and nearly as good (not quite) as when using AES. A slight advantage is that the same constant is used twice (it did make it slightly faster the last time I tested, not sure if it's still the case).

    You can reverse the process (get the input value from the hash) if you replace the 0x45d9f3b with 0x119de1f3 (the multiplicative inverse):

    unsigned int unhash(unsigned int x) {
        x = ((x >> 16) ^ x) * 0x119de1f3;
        x = ((x >> 16) ^ x) * 0x119de1f3;
        x = (x >> 16) ^ x;
        return x;
    }
    

    For 64-bit numbers, I suggest to use the following, even thought it might not be the fastest. This one is based on splitmix64, which seems to be based on the blog article Better Bit Mixing (mix 13).

    uint64_t hash(uint64_t x) {
        x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
        x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
        x = x ^ (x >> 31);
        return x;
    }
    

    For Java, use long, add L to the constant, replace >> with >>> and remove unsigned. In this case, reversing is more complicated:

    uint64_t unhash(uint64_t x) {
        x = (x ^ (x >> 31) ^ (x >> 62)) * UINT64_C(0x319642b2d24d8ec3);
        x = (x ^ (x >> 27) ^ (x >> 54)) * UINT64_C(0x96de1b173f119089);
        x = x ^ (x >> 30) ^ (x >> 60);
        return x;
    }
    

    Update: You may also want to look at the Hash Function Prospector project, where other (possibly better) constants are listed.

    0 讨论(0)
  • 2020-11-22 17:57
    • 32-bits multiplicative method (very fast) see @rafal

      #define hash32(x) ((x)*2654435761)
      #define H_BITS 24 // Hashtable size
      #define H_SHIFT (32-H_BITS)
      unsigned hashtab[1<<H_BITS]  
      .... 
      unsigned slot = hash32(x) >> H_SHIFT
      
    • 32-bits and 64-bits (good distribution) at : MurmurHash

    • Integer Hash Function
    0 讨论(0)
  • 2020-11-22 17:57

    I have been using splitmix64 (pointed in Thomas Mueller's answer) ever since I found this thread. However, I recently stumbled upon Pelle Evensen's rrxmrrxmsx_0, which yielded tremendously better statistical distribution than the original MurmurHash3 finalizer and its successors (splitmix64 and other mixes). Here is the code snippet in C:

    #include <stdint.h>
    
    static inline uint64_t ror64(uint64_t v, int r) {
        return (v >> r) | (v << (64 - r));
    }
    
    uint64_t rrxmrrxmsx_0(uint64_t v) {
        v ^= ror64(v, 25) ^ ror64(v, 50);
        v *= 0xA24BAED4963EE407UL;
        v ^= ror64(v, 24) ^ ror64(v, 49);
        v *= 0x9FB21C651E98DF25UL;
        return v ^ v >> 28;
    }
    

    Pelle also provides an in-depth analysis of the 64-bit mixer used in the final step of MurmurHash3 and the more recent variants.

    0 讨论(0)
  • 2020-11-22 17:58

    There's a nice overview over some hash algorithms at Eternally Confuzzled. I'd recommend Bob Jenkins' one-at-a-time hash which quickly reaches avalanche and therefore can be used for efficient hash table lookup.

    0 讨论(0)
  • 2020-11-22 17:59

    This page lists some simple hash functions that tend to decently in general, but any simple hash has pathological cases where it doesn't work well.

    0 讨论(0)
提交回复
热议问题