Есть ли способ принудительно переполнить круговое целое в Excel VBA? - PullRequest
4 голосов
/ 14 марта 2011

Я пытаюсь преобразовать некоторый код 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 голосов
/ 15 марта 2011

Хотя нет встроенного способа сделать это, вычисления просты:

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]).

0 голосов
/ 14 марта 2011

Я немного изменил наш скрипт.Основным отличием является возвращаемый тип вашей функции.Теперь он возвращает Variant .Поскольку decimal - это подмножество 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...