在Excel VBA中,有没有一种方法可以强制进行循环整数溢出?

4

我正在尝试将一些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个回答

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 * [某个整数>= 1058])时引发溢出错误。


谢谢,我最终不得不将它从整数和长整型更改为长整型和小数以适用于我的应用程序(当我提出问题时我没有意识到这是必要的),但除此之外完全正确。 - user69820

0

我稍微修改了我们的脚本。主要区别是您函数的返回类型。现在它返回Variant。由于十进制是 Variant 的子集,而且它可以存储比 long 更大的数字,所以我认为这是一个好的解决方案(请参阅 VBA 数据类型)- 我不知道是否可能显式地返回 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

我找不到如何定义Decimal类型的变量,只知道强制转换函数是**CDec()**。 - MPękalski
感谢您的回复@MPękalski,但我实际上仍希望值溢出。如果我想存储比“long”更大的数字,这是正确的答案。 - user69820
抱歉,我可能匆忙了,没有看到您想要在溢出时将值设为负数。目前我不知道如何做到这一点,除非在我的脚本中添加一个条件,如果它大于Long,则返回一个负数等等... - MPękalski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接