【问题标题】:is it possible for MurmurHash3 to produce a 64 bit hash where the upper 32 bits are all 0?MurmurHash3 是否有可能产生一个高 32 位全为 0 的 64 位散列?
【发布时间】:2016-11-05 16:48:47
【问题描述】:

看着https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp我不这么认为,但我想检查一下。

情况是这样的,如果我有一个 1,2,3 或 4 个字节的键,简单地取这些字节的数值而不是散列到 8 个字节是否可靠,或者这些会导致键冲突用 murmur3 散列的大于 4 个字节?

【问题讨论】:

    标签: c++ hash murmurhash


    【解决方案1】:

    这样的属性是散列函数的属性。它有效地缩小了函数共域,增加了碰撞机会,所以看起来不太可能。

    另外,this blog post 为 MurmurHash 提供了一个反转函数:

    uint64 murmur_hash_64(const void * key, int len, uint64 seed)
    {
        const uint64 m = 0xc6a4a7935bd1e995ULL;
        const int r = 47;
    
        uint64 h = seed ^ (len * m);
    
        const uint64 * data = (const uint64 *)key;
        const uint64 * end = data + (len / 8);
    
        while (data != end)
        {
    #ifdef PLATFORM_BIG_ENDIAN
            uint64 k = *data++;
            char *p = (char *)&k;
            char c;
            c = p[0]; p[0] = p[7]; p[7] = c;
            c = p[1]; p[1] = p[6]; p[6] = c;
            c = p[2]; p[2] = p[5]; p[5] = c;
            c = p[3]; p[3] = p[4]; p[4] = c;
    #else
            uint64 k = *data++;
    #endif
    
            k *= m;
            k ^= k >> r;
            k *= m;
    
            h ^= k;
            h *= m;
        }
    
        const unsigned char * data2 = (const unsigned char*)data;
    
        switch (len & 7)
        {
        case 7: h ^= uint64(data2[6]) << 48;
        case 6: h ^= uint64(data2[5]) << 40;
        case 5: h ^= uint64(data2[4]) << 32;
        case 4: h ^= uint64(data2[3]) << 24;
        case 3: h ^= uint64(data2[2]) << 16;
        case 2: h ^= uint64(data2[1]) << 8;
        case 1: h ^= uint64(data2[0]);
            h *= m;
        };
    
        h ^= h >> r;
        h *= m;
        h ^= h >> r;
    
        return h;
    }
    
    uint64 murmur_hash_64_inverse(uint64 h, uint64 seed)
    {
        const uint64 m = 0xc6a4a7935bd1e995ULL;
        const uint64 minv = 0x5f7a0ea7e59b19bdULL; // Multiplicative inverse of m under % 2^64
        const int r = 47;
    
        h ^= h >> r;
        h *= minv;
        h ^= h >> r;
        h *= minv;
    
        uint64 hforward = seed ^ (((uint64)8) * m);
        uint64 k = h ^ hforward;
    
        k *= minv;
        k ^= k >> r;
        k *= minv;
    
    #ifdef PLATFORM_BIG_ENDIAN
        char *p = (char *)&k;
        char c;
        c = p[0]; p[0] = p[7]; p[7] = c;
        c = p[1]; p[1] = p[6]; p[6] = c;
        c = p[2]; p[2] = p[5]; p[5] = c;
        c = p[3]; p[3] = p[4]; p[4] = c;
    #endif
    
        return k;
    }
    

    您可以找到任意数量的带有哈希值&lt;2^32 的输入。

    您关于可靠性的问题没有多大意义:您必须始终准备好正确处理碰撞。根据我的实践,我不建议使用纯整数或指针值作为哈希值,因为它们会产生不希望的模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2012-07-13
      • 2010-12-03
      • 1970-01-01
      • 1970-01-01
      • 2010-10-09
      • 2011-05-06
      相关资源
      最近更新 更多