Есть ли функция VB для преобразования 32-битного числа с плавающей запятой в бит с прямым порядком байтов? - PullRequest
0 голосов
/ 13 июля 2020

Как показано здесь: https://gregstoll.com/~gregstoll/floattohex/ Мне нужно преобразовать 32-битное число с плавающей запятой в шестнадцатеричный формат с прямым порядком байтов (перед преобразованием нажмите кнопку окончания замены). Мне удалось сделать это в python, преобразовав в big endian, а затем переупорядочив, но я понятия не имею, как подойти к этой проблеме в VB, поскольку я совершенно новичок в этом языке. Использование встроенной функции Hex возвращает 19a, что, как я полагаю, означает, что он неправильно оценивает мой ввод как единый.

Я нашел здесь рекомендуемое решение, но не могу заставить его работать: https://www.tek-tips.com/faqs.cfm?fid=6404

Любые предложения были бы замечательными, заранее спасибо.

1 Ответ

2 голосов
/ 14 июля 2020

Есть несколько способов сделать это, наиболее очевидным из которых является Copy Memory API. Некоторое время go, здесь было опубликовано довольно изящное решение: Извлечение битов из числа с плавающей запятой в vba , что позволяет избежать необходимости в API

По сути, вам просто понадобится пара коротких функций:

Option Explicit

Type SingleType
  Value As Single
End Type
Type FourBytesType
  Value(3) As Byte
End Type

Private Function SingleToBytes(f As Single) As Variant
    Dim sngType As SingleType
    Dim bytesType As FourBytesType
    
    sngType.Value = f
    LSet bytesType = sngType
    SingleToBytes = bytesType.Value
End Function

Private Function BytesToHex(bytes As Variant) As String
    Dim result As String
    Dim i As Long
    
    For i = LBound(bytes) To UBound(bytes)
        result = result & IIf(bytes(i) < 16, "0", "") & Hex(bytes(i))
    Next
    BytesToHex = result
    
End Function

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

Private Function IsLittleEndianProcessor() As Boolean
    Const BOM As Single = 1
    Const MSB As Byte = 63
    Dim bytes() As Byte
    Dim n As Long
    
    bytes = SingleToBytes(BOM)
    n = UBound(bytes)
    IsLittleEndianProcessor = (bytes(n) = MSB)
    
End Function

Private Function ChangeEndianness(bytes As Variant) As Variant
    Dim result() As Byte
    Dim n As Long, m As Long
    
    ReDim result(UBound(bytes))
    m = UBound(bytes)
    For n = LBound(bytes) To UBound(bytes)
        result(m) = bytes(n)
        m = m - 1
    Next
    
    ChangeEndianness = result
End Function

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

Public Sub TestMe()
    Dim bytes As Variant
    Dim output As String
    
    bytes = SingleToBytes(3.1415)
    
    If Not IsLittleEndianProcessor Then
        bytes = ChangeEndianness(bytes)
    End If
    output = BytesToHex(bytes)
    Debug.Print output
    
End Sub
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...