Me encontré con esta pregunta SO que preguntaba sobre una forma para convertir valores hexadecimales más grandes en un valor numérico positivo:

?Val("&H8000") -32768 Val("&HFFFF") -1 

Mi respuesta implicó iterar los dígitos de la cadena uno por uno y calcular su valor respectivo en el resultado:

Function ConvertHex(ByVal value As String) As Double If Left(value, 2) = "&H" Then value = Right(value, Len(value) - 2) End If Dim result As Double Dim i As Integer, j As Integer For i = Len(value) To 1 Step -1 Dim digit As String digit = Mid$(value, i, 1) result = result + (16 ^ j) * Val("&H" & digit) j = j + 1 Next ConvertHex = result End Function 

Funciona, pero puedo » Ayude a pensar que he hecho algo estúpidamente demasiado complicado por algo que debería ser bastante simple.

Hay una mejor manera, ¿no es así?

Comentarios

  • Estoy ' confundido en cuanto a lo que quieres lograr. " El doble " normalmente significa un número de coma flotante de 64 bits. Sin embargo, tu texto dice que quieres un " valor numérico positivo ", pero luego tus ejemplos parecen mostrar firmado Números enteros de 16 bits (generalmente llamados " short "). Además, parece que solo se pueden representar números enteros en la cadena hexadecimal, por lo que el tipo de retorno debe ser Short, Integer, Long, UShort, UInteger, ULong, o Decimal.
  • @ 200_success Hay ' s solo un conjunto muy limitado de tipos de datos en VBA. No hay tipos sin firmar …
  • Mat, ¿qué ' está mal con Cdbl("&HFFFF")?
  • @Meehow vea la actualización de mi respuesta de por qué creo que CDbl es incorrecto para este escenario.
  • @Meehow eso es exactamente lo que quise decir con " Yo ' he hecho algo estúpidamente demasiado complicado para algo que debería ser bastante simple " 😉

Responder

Por lo que puedo decir, una cadena que comienza con &H es un literal hexadecimal.

Existe un número de funciones de conversión que pueden convertir una expresión al tipo deseado.

Por lo tanto, debería ser simplemente, según el tipo deseado:

Function ConvertHex(ByVal value As String) As Currency Dim result As Currency result = CCur(value) If result < 0 Then "Add two times Int32.MaxValue and another 2 for the overflow "Because the hex value is apparently parsed as a signed Int64/Int32 result = result + &H7FFFFFFF + &H7FFFFFFF + 2 End If ConvertHex = result End Function 

Moneda vs Doble

Valor entero positivo máximo representable con precisión:

Entonces, ¿por qué usar Currency sobre Double cuando este último funciona para un rango mayor de números enteros?

Currency es siempre precisa. Si desbordamos un valor Currency obtenemos un error. Si sobrepasamos el valor entero máximo representable de un doble, obtenemos un valor entero aproximado:

Dim doubleMax As Double Dim doubleAfter As Double doubleMax = CDbl("&H0020000000000000") doubleAfter = doubleMax + 1 MsgBox "Double before: " & Format(doubleMax, "#") & vbNewLine & "after: " & Format(doubleAfter, "#") Dim currencyMax As Currency Dim currencyAfter As Currency currencyMax = CCur("&H000346DC5D638865") currencyAfter = currencyMax + 1 MsgBox "Currency before: " & Format(currencyMax, "#") & vbNewLine & "after: " & Format(currencyAfter, "#") 

La salida de este ejemplo es:

 Double before: 9007199254740990 after: 9007199254740990  

Y luego un run-time error "6": Overflow que es genial si quiere evitar errores de redondeo. Ahora MSDN afirma que Double está

almacenado como número de punto flotante IEEE de 64 bits (8 bytes)

pero si «ha leído algo sobre el IEEE 754 binary64 debería estar un poco sorprendido por el resultado del ejemplo. El máximo real es &H00038D7EA4C68000 (1,000,000,000,000,000).

Comentarios

  • ¡Genial! ' he vinculado esta respuesta en una edición de mi respuesta SO 🙂
  • Amplié el bit sobre Currency vs Double un poco y descubrió algo interesante.
  • ¿Qué tal si doubleMax + doubleMax lanza un ¿Error de desbordamiento?
  • @Meehow Acabo de probarlo y aparentemente Double en VBA se desborda. Pero ' todavía no es posible desbordar si el resultado analizado es un número entero. Yo ' me alegro de no haberlo ' No tengo que trabajar con ese idioma.
  • La forma correcta e idiomática de hacer esto es usar una de las funciones de conversión integradas, como @Meehow comentó en el OP – No ' no sé qué pedo cerebral me hizo escribir esta función …

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *