Преобразование шестнадцатеричных (A-F) чисел - PullRequest
0 голосов
/ 19 марта 2019

Я сделал функцию для преобразования чисел.например, от основания 5 до основания 15 - означают другие типы, кроме базовых 2, 8, 10, 16. Они основаны на преобразовании числа в основание 10 (с использованием степеней), а затем из основания 10 в другое основание (mod, div).

Существует проблема с вводом значений AF (шестнадцатеричное число является верхним).

Это отдельная часть кода, которая преобразует число в основание 10.

Function prevdeset(base As Integer, ipt As String) As String
Dim x As Integer
Dim s As Integer
Dim u As Integer
Dim p As Integer
c = Str(ipt)
x = Len(ipt)
u = 0
For i = x To 1 Step -1
    If Mid(c, i, 1) = "A" Then
        p = 10
    ElseIf Mid(c, i, 1) = "B" Then
        p = 11
    ElseIf Mid(c, i, 1) = "C" Then
        p = 12
    ElseIf Mid(c, i, 1) = "D" Then
        p = 13
    ElseIf Mid(c, i, 1) = "E" Then
        p = 14
    ElseIf Mid(c, i, 1) = "F" Then
        p = 15
    Else: p = Val(Mid(c, i, 1))
    End If
    p = p * (base ^ (x - i))
    u = u + p
Next i
prevdeset = u
End Function

Функция выбирает i-й символ справа и сначала проверяет, является ли строковое значение A - если нет, то B, C, D, E, F, и если ничего из этого, она должна преобразовать символ в число (Iне пытайтесь вводить другие буквы как G, H ..).

Нет проблем с выводом, если ввод не является строкой, и полный код (здесь не показан) может выводить буквы (Пример: 10 в базе 10 будет A в базе 14).

Ответы [ 2 ]

1 голос
/ 19 марта 2019

Вы получаете ошибку переполнения из-за ограничения VBA на Integers.Измените ваши переменные на Long, и ваш код работает

| Type    | Storage | Range of Values                 |
|---------|---------|---------------------------------|
| Byte    | 1 byte  | 0 to 255                        |
| Integer | 2 bytes | -32,768 to 32,767               |
| Long    | 4 bytes | -2,147,483,648 to 2,147,483,647 |

Option Explicit
Function prevdeset(base As Integer, ipt As String) As String
    Dim x As Long, s As Long, u As Long, p As Long
    Dim i As Long
    Dim c As String

    c = ipt
    x = Len(ipt)
    u = 0
    For i = x To 1 Step -1
        If Mid(c, i, 1) = "A" Then
        p = 10
        ElseIf Mid(c, i, 1) = "B" Then
        p = 11
        ElseIf Mid(c, i, 1) = "C" Then
        p = 12
        ElseIf Mid(c, i, 1) = "D" Then
        p = 13
        ElseIf Mid(c, i, 1) = "E" Then
        p = 14
        ElseIf Mid(c, i, 1) = "F" Then
        p = 15
        Else: p = Val(Mid(c, i, 1))
        End If
        p = p * (base ^ (x - i))
        u = u + p
    Next i
    prevdeset = u
End Function

Sub test()
    Dim HexVal As String
    HexVal = "7B19AB"

    Debug.Print CLng("&H" & HexVal)
    Debug.Print prevdeset(16, HexVal)
End Sub

Кроме того, вам не нужно конвертировать ipt в String - вы уже объявили ipt как String.Вы можете заставить c быть строкой, просто объявив ее (вы должны всегда объявлять все свои переменные удобной привычкой для реализации этой практики, чтобы гарантировать, что все ваши модули имеют Option Explicit вверху).

Фактически ваш код может быть сокращен до:

Function prevdeset(base As Integer, ipt As String) As String
    Dim i As Long, u As Long
    Dim p As Long
    Dim HexCode As String

    For i = Len(ipt) To 1 Step -1
        HexCode = UCase(Mid(ipt, i, 1))

        If Not IsNumeric(HexCode) Then
            p = Asc(HexCode) - Asc("A") + 10
            If p >= base Then Err.Raise Number:=999, Source:="prevdeset", Description:="Invalid Hex"
        Else
            p = Val(HexCode)
        End If

        p = p * (base ^ (Len(ipt) - i))
        u = u + p
    Next i
    prevdeset = u
End Function
0 голосов
/ 19 марта 2019

Код ниже является вашей упрощенной и исправленной версией.Причина, по которой ваш код не работает, заключается в использовании целых чисел вместо, по крайней мере, длинных.Я предлагаю LongPtr.

Function Prevdeset(ByVal base As Integer, ByVal ipt As String) As LongPtr
    ' pass the arguments ByVal to avoid having them changed by the code
    ' in this way you wouldn't need the variable ipt
    ' Add Option Explicit at the top of your code module
    ' to ensure that you don't forget to declare variables

    Dim u As LongPtr
    Dim p As Integer
    Dim x As Integer
    Dim i As Integer
    ' the Dim statement sets all values to 0

    x = Len(ipt)
    For i = x To 1 Step -1
        p = InStr("0123456789ABCDEF", Mid(ipt, i, 1)) - 1
        If p < 0 Then
            MsgBox "invalid characer " & Mid(ipt, i, 1) & "." & vbCr & _
                   "The returned result may not be correct."
        End If

        u = u + (p * (base ^ (x - i)))
    Next i
    Prevdeset = u
End Function

Обратите внимание, что тип возвращаемого значения функции должен совпадать с назначенным переменной u (LongPtr в моем коде, но, по крайней мере, Long).Если вы хотите, чтобы функция возвращала строку, вы можете присвоить Prevdeset = CStr(u) в последней строке кода функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...