package hash32 /* * ***注意*** * * Sum 使用的是[]byte参数;string中文是utf-8编码 * SumByRune 使用的是[]rune参数;中文使用的是unicode编码 * * 两种参数中文编码不同;同一个string调用两个接口得到的hash是不同的!!! 这是要特别注意的 * * 对string进行for range操作会自动被[]rune化;一定要注意!!! * */ const shiftBit = 11 // 每个字节移位数(测试经验值11) const reverseBit = 32 - shiftBit // 快速Hash计算(*** 注意:只取了rune低16位进行hash计算;计算结果与SumByRune不一致 ***) func FastSumByRune2(in rune, hs uint32) (out uint32) { out = ((hs << shiftBit) | (hs >> reverseBit)) + uint32(byte(in>>8)) out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in)) return } // 快速Hash计算(*** 此计算结果与SumByRune一致 ***) func FastSumByRune4(in rune, hs uint32) (out uint32) { out = ((hs << shiftBit) | (hs >> reverseBit)) + uint32(byte(in>>24)) out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in>>16)) out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in>>8)) out = ((out << shiftBit) | (out >> reverseBit)) + uint32(byte(in)) return } // 原Hash值参数重 func hsArg(hsOpt ...uint32) (out uint32) { out = uint32(0) if len(hsOpt) > 0 { out = hsOpt[0] } return } // Hash计算 // in - 待hash串 // hsOpt - 原hash值(在此基础上继续hash) func Sum(in []byte, hsOpt ...uint32) (out uint32) { out = hsArg(hsOpt...) for _, v := range in { out = ((out << shiftBit) | (out >> reverseBit)) + uint32(v) } return } // Hash计算 func SumByRune(in rune, hsOpt ...uint32) (out uint32) { // rune转[]byte inVal := make([]byte, 4) inVal[0] = byte(in >> 24) inVal[1] = byte(in >> 16) inVal[2] = byte(in >> 8) inVal[3] = byte(in) // *** 经实际测试:不加以下代码运行效率更高 *** // 去除前面多余的\x00 // for { // if len(inVal) <= 1 { // // 以免全0异常;至少要保留1位 // break // } // if inVal[0] == 0 { // inVal = inVal[1:] // } else { // break // } // } // 规避hash冲突,如:"N-"与"中"unicode编码均为#4E2D,即会产生hash冲突 // 若长度>1(即非常规ASCII),所有字节最高位置1 // if len(inVal) > 1 { // for i := 0; i < len(inVal); i++ { // inVal[i] |= 0x80 // } // } out = Sum(inVal, hsOpt...) return } // Hash计算 func SumByRunes(in []rune, hsOpt ...uint32) (out uint32) { out = hsArg(hsOpt...) for _, v := range in { out = SumByRune(v, out) } return }