goProject/trunk/goutil/dfaExUtil/hash32/hash32.go

99 lines
2.5 KiB
Go
Raw Normal View History

2025-01-06 16:01:02 +08:00
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
}