有没有办法在Excel VBA中强制循环整数溢出?

时间:2011-03-14 14:31:37

标签: vba

我正在尝试将一些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中执行此操作?

2 个答案:

答案 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