golang有用的库及工具 之 字符串转换 获取32位 uint32位hash 方法 MurmurHash哈希

MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。由Austin Appleby在2008年发明,并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。


const (
   c1_32 uint32 = 0xcc9e2d51
   c2_32 uint32 = 0x1b873593
)

// GetHash returns a murmur32 hash for the data slice.
func GetHash(data []byte) uint32 {
   // Seed is set to 37, same as C# version of emitter
   var h1 uint32 = 37

   nblocks := len(data) / 4
   var p uintptr
   if len(data) > 0 {
      p = uintptr(unsafe.Pointer(&data[0]))
   }

   p1 := p + uintptr(4*nblocks)
   for ; p < p1; p += 4 {
      k1 := *(*uint32)(unsafe.Pointer(p))

      k1 *= c1_32
      k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
      k1 *= c2_32

      h1 ^= k1
      h1 = (h1 << 13) | (h1 >> 19) // rotl32(h1, 13)
      h1 = h1*5 + 0xe6546b64
   }

   tail := data[nblocks*4:]

   var k1 uint32
   switch len(tail) & 3 {
   case 3:
      k1 ^= uint32(tail[2]) << 16
      fallthrough
   case 2:
      k1 ^= uint32(tail[1]) << 8
      fallthrough
   case 1:
      k1 ^= uint32(tail[0])
      k1 *= c1_32
      k1 = (k1 << 15) | (k1 >> 17) // rotl32(k1, 15)
      k1 *= c2_32
      h1 ^= k1
   }

   h1 ^= uint32(len(data))

   h1 ^= h1 >> 16
   h1 *= 0x85ebca6b
   h1 ^= h1 >> 13
   h1 *= 0xc2b2ae35
   h1 ^= h1 >> 16

   return (h1 << 24) | (((h1 >> 8) << 16) & 0xFF0000) | (((h1 >> 16) << 8) & 0xFF00) | (h1 >> 24)
}



测试:

func TestGetHash2(t *testing.T) {
   h := GetHash([]byte("hello world"))
   if h != 4008393376 {
      t.Errorf("Hash %d is not equal to %d", h, 1815237614)
   }
}


总结:这个方法可以用于 内存中字符串 映射为 32位int型 数字,以提高内存的使用映射率


可以使用golanghash/crc32包来计算simhash算法中的哈希值,具体实现可以参考以下代码: ``` package simhash import ( "bytes" "hash/crc32" ) // Simhash represents a 64-bit hash value type Simhash uint64 // NewSimhash calculates the simhash of the given data func NewSimhash(data []byte) Simhash { // Step 1: tokenize data into shingles shingles := tokenize(data) // Step 2: compute the weighted frequency counts of shingles counts := countShingles(shingles) // Step 3: create the simhash var simhash Simhash for shingle, weight := range counts { hash := crc32.ChecksumIEEE([]byte(shingle)) for i := 0; i < 32; i++ { if hash&(1<<uint(i)) != 0 { simhash += Simhash(weight) } else { simhash -= Simhash(weight) } } } return simhash } // tokenize splits the given data into shingles func tokenize(data []byte) []string { shingles := make([]string, 0) var buffer bytes.Buffer for i := 0; i < len(data); i++ { if data[i] == ' ' { shingles = append(shingles, buffer.String()) buffer.Reset() continue } buffer.WriteByte(data[i]) } if buffer.Len() > 0 { shingles = append(shingles, buffer.String()) } return shingles } // countShingles computes the weighted frequency counts of the given shingles func countShingles(shingles []string) map[string]int { counts := make(map[string]int) for _, shingle := range shingles { counts[shingle]++ } return counts } ``` 这段代码实现了simhash算法的三个步骤:将输入数据分割为shingles,计算shingles的加权频率,以及计算simhash值。其中,crc32包用于计算哈希值,bytes包用于处理字符串
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值