我正在尝试将一些Java代码转换为Excel,并且所需的哈希码函数会生成溢出错误,而不是包装到负面
Function FnGetStringHashCode(ByVal str As String) As Integer
Dim result, i
FnGetStringHashCode = 17
For i = 1 To Len(str)
Dim c, a
c = Mid(str, i, 1)
a = AscW(c)
FnGetStringHashCode = 31 * FnGetStringHashCode + a
Next i
End Function
有没有办法在Excel VBA中执行此操作?
答案 0 :(得分:3)
虽然没有内置方法可以做到这一点,但计算很简单:
Public Function coerceLongToInt(toCoerce As Long) As Integer
Const MIN_INT As Long = -32768
Const MAX_INT As Long = 32767
Const NUM_INTS As Long = MAX_INT - MIN_INT + 1
Dim remainder As Long
remainder = toCoerce Mod NUM_INTS
If remainder > MAX_INT Then
coerceLongToInt = remainder - NUM_INTS
ElseIf remainder < MIN_INT Then
coerceLongToInt = remainder + NUM_INTS
Else
coerceLongToInt = remainder
End If
End Function
这是你想要的行为,对吧?
?coerceLongToInt(-32769)
32767
?coerceLongToInt(-32768)
-32768
?coerceLongToInt(-1)
-1
?coerceLongToInt(0)
0
?coerceLongToInt(1)
1
?coerceLongToInt(32767)
32767
?coerceLongToInt(32768)
-32768
您可以这样使用它:
Function FnGetStringHashCode(ByVal str As String) As Integer
Dim result, i
FnGetStringHashCode = 17
For i = 1 To Len(str)
Dim c, a
c = Mid(str, i, 1)
a = AscW(c)
FnGetStringHashCode = coerceLongToInt(31 * CLng(FnGetStringHashCode) + a)
Next i
End Function
你需要在那里调用'CLng'来防止VBA在计算中间值(31 * [某个整数&gt; = 1058])时引发溢出错误。
答案 1 :(得分:0)
我修改了一下我们的剧本。主要区别在于返回函数的类型。现在它返回变体。由于十进制是Variant的一个子集,并且它可以存储比较长的数字,我认为这是一个很好的解决方案(see VBA data types) - 我不知道是否可以显式返回Decimal。这是脚本
Function FnGetStringHashCode(ByVal str As String) As Variant
Dim tmp As Variant, c As String, a As Integer, i As Integer
tmp = 17
For i = 1 To Len(str)
c = Mid$(str, i, 1)
a = AscW(c)
tmp = 31 * tmp + a
Next i
FnGetStringHashCode = tmp
End Function
还有一点测试程序
Sub test()
Debug.Print CStr(FnGetStringHashCode("dawdaedae"))
End Sub