這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Simhash的演算法簡單的來說就是,從海量文本中快速搜尋和已知simhash相差小於k位的simhash集合,這裡每個文本都可以用一個simhash值來代表,一個simhash有64bit,相似的文本,64bit也相似,論文中k的經驗值為3。該方法的缺點如優點一樣明顯,主要有兩點,對於短文本,k值很敏感;另一個是由於演算法是以空間換時間,系統記憶體吃不消。
demo:
package mainimport ( "fmt" "math" "strconv" "strings")type SimHash struct { IntSimHash int64 HashBits int}func main() { str := "夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息" str2 := "夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息夜空中最亮的星是否記清那仰望的人 心裡的孤獨和歎息" //str3:="nai nai ge xiong cao" s := params() //str hash 值 hash := s.Simhash(str) fmt.Println(hash) //str2 距離 hash2 := s.Simhash(str2) fmt.Println(hash2) //計算相似性 sm := s.Similarity(hash, hash2) fmt.Println(sm) //距離 ts := s.HammingDistance(hash, hash2) fmt.Println(ts)}/** 距離 補償 */func (s *SimHash) HammingDistance(hash, other int64) int { x := (hash ^ other) & ((1 << uint64(s.HashBits)) - 1) tot := 0 for x != 0 { tot += 1 x &= x - 1 } return tot}/** 相似性 */func (s *SimHash) Similarity(hash, other int64) float64 { a := float64(hash) b := float64(other) if a > b { return b / a } return a / b}/** 海明距離hash */func (s *SimHash) Simhash(str string) int64 { m := strings.Split(str, " ") token_int := make([]int, s.HashBits) for i := 0; i < len(m); i++ { temp := m[i] t := s.Hash(temp) for j := 0; j < s.HashBits; j++ { bitMask := int64(1 << uint(j)) if t&bitMask != 0 { token_int[j] += 1 } else { token_int[j] -= 1 } } } var fingerprint int64 = 0 for i := 0; i < s.HashBits; i++ { if token_int[i] >= 0 { fingerprint += 1 << uint64(i) } } return fingerprint}/** 初始化 */func params() (s *SimHash) { s = &SimHash{} s.HashBits = 64 return s}/**hash 值 */func (s *SimHash) Hash(token string) int64 { if token == "" { return 0 } else { x := int64(int(token[0]) << 7) m := int64(1000003) mask := math.Pow(2, float64(s.HashBits-1)) s := strconv.FormatFloat(mask, 'f', -1, 64) tsk, _ := strconv.ParseInt(s, 10, 64) for i := 0; i < len(token); i++ { tokens := int64(int(token[0])) x = ((x * m) ^ tokens) & tsk } x ^= int64(len(token)) if x == -1 { x = -2 } return int64(x) }}