我想将this simple hash algorithm移植到VB6。
我想出了:
Public Function simpleHash(hashString As String) As Long
Dim hash As Long
Dim c As Long
Dim i As Integer
On Local Error Resume Next
hash = 5381
For i = 1 To Len(hashString)
c = AscW(Mid$(hashString, i, 1))
hash = hash * 33 + c
Next i
simpleHash = hash
End Function
问题是,尽管我的On Error
语句抑制了错误6:溢出异常,但如果发生溢出,变量hash
不会再更新。
如何解决这个问题或以不同方式实施此算法?
答案 0 :(得分:3)
我会怀疑以这种方式散列UTF-16LE(" Unicode")是否有意义。将VB字符串转换为UTF-8 然后哈希可能会更有意义。
虽然我无法找到 djb2 的任何测试向量来验证我自己的实现,但它似乎运行得很快:
Private Type CURRENCY_CURRENCY
Value As Currency
End Type
Private Type CURRENCY_2LONGS
ValueLo As Long
ValueHi As Long
End Type
Public Function djb2(ByVal StringToHash As String) As Long
Dim C2L As CURRENCY_2LONGS
Dim CC As CURRENCY_CURRENCY
Dim I As Long
C2L.ValueLo = 5381
For I = 1 To Len(StringToHash)
LSet CC = C2L
CC.Value = CC.Value * 33@ + CCur(AscW(Mid$(StringToHash, I, 1))) / 10000@
LSet C2L = CC
C2L.ValueHi = 0
Next I
djb2 = C2L.ValueLo
End Function
答案 1 :(得分:2)
我找到了一个解决方法,使用 Currency 并自己进行溢出数学运算(事实证明VB6 Mod
运算符也不能在Currency
上运行):
Const pow2_32 As Currency = 2@ ^ 32
Const signed32Max As Currency = 2@ ^ 31 - 1
Public Function simpleHash(hashString As String) As Long
Dim hash As Currency
Dim i As Long
hash = 5381
For i = 1 To Len(hashString)
hash = hash * 33@ + CCur(AscW(Mid$(hashString, i, 1)))
While hash >= pow2_32
hash = hash - pow2_32
Wend
Next i
If hash > signed32Max Then
hash = hash - pow2_32
End If
simpleHash = CLng(hash)
End Function
但是,请参阅Bob77's answer以获得几乎是我的解决方案速度的两倍的解决方案。