Trucos Operaciones con números de 64 bits (8 bytes)

Extraído del artículo Q189862 de la KB de Microsoft.

INTRODUCCIÓN
Muchas funciones del API de Windows requieren un valor de 64 bits, bien como un entero de 8 bytes, bien como dos enteros de 4 bytes. Veremos cómo convertir datos entre un entero de 8 bytes y dos enteros de 4 bytes. También veremos cómo hacer operaciones matemáticas simples con ellos, como las que se necesitan para incrementar el puntero a fichero del API SetFilePointer.

MAS INFORMACION
Visual Basic posee un tipo de datos entero de 8 bytes llamado Currency pero está escalado en por un factor de 0,0001 para entrada, salida y operacione matemáticas. Esto no impide que lo usemos como argumento en llamadas al API que requieren un número de 64 bits. En es artículo veremos algunas rutinas de conversión y operaciones matemáticas básicas que tienen en cuenta este factor de escala.

Existen dos maneras de convertir entre dos valores de 32 bits y uno de 64 :
- Podemos usar la instrucción LSet y tipos definidos por el usuario
- Podemos emplear la funcion del API CopyMemory

Veremos cómo usar LSet.

Los ejemplos emplearán los siguiente tipos definidos por el usuario :

   Type MungeCurr
     Value As Currency
   End Type

   Type Munge2Long
     LoValue As Long
     HiValue As Long
   End Type

Convertir dos valores de 32 bits en uno de 64.
   Dim C As MungeCurr, L As Munge2Long
   L.HiValue = Value1
   L.LoValue = Value2
   LSet C = L
   Value3 = C.Value

Convertir un valor de 64 bits en dos de 32.
   Dim C As MungeCurr, L As Munge2Long
   C.Value = Value1
   LSet L = C
   Value2 = L.HiValue
   Value3 = L.LoValue

Formatear un valor Currency sin posiciones decimales
Esta rutina tiene en cuenta que si el número tiene menos de 4 dígitos se eliminan los ceros de la izquierda dejando el signo intacto.

NOTA : Esta rutina asume que el separador decimal es "." (punto) y el signo menos es "-" y está a la izquierda del número.

   Private Function CurrToText(ByVal Value As Currency) As String
   Dim Temp As String, L As Long
     Temp = Format$(Value, "#.0000")
     L = Len(Temp)
     Temp = Left$(Temp, L - 5) & Right$(Temp, 4)
     Do While Len(Temp) > 1 And Left$(Temp, 1) = "0"
       Temp = Mid$(Temp, 2)
     Loop
     Do While Len(Temp) > 2 And Left$(Temp, 2) = "-0"
       Temp = "-" & Mid$(Temp, 3)
     Loop
     CurrToText = Temp
   End Function

Convertir un campo de texto sin decimales en un Currency.
Esta rutina tiene en cuenta que si el número tiene menos de 4 dígitos habrá que rellenarlo y adecuar el signo.

NOTA : Esta rutina asume que el separador decimal es "." (punto) y el signo menos es "-" y está a la izquierda del número.

   Private Function TextToCurr(ByVal Value As String) As Currency
   Dim L As Long, Negative As Boolean
     Value = Trim$(Value)
     If Left$(Value, 1) = "-" Then
       Negative = True
       Value = Mid$(Value, 2)
     End If
     L = Len(Value)
     If L < 4 Then
       TextToCurr = CCur(IIf(Negative, "-0.", "0.") & _
                         Right$("0000" & Value, 4))
     Else
       TextToCurr = CCur(IIf(Negative, "-", "") & _
                         Left$(Value, L - 4) & "." & Right$(Value, 4))
     End If
   End Function

Sumar o restar dos conjuntos de 32 bits.
Este procedimiento no requiere especial consideración. Los pasos a seguir son :
- Convertir los cuatro valores de 32 bits en 2 de 64.
- Sumar los valores de 64 bits.
- Convertir el resultado de 64 bits en dos de 32.

Multiplicar y dividir valores de 64 bits.
Cuando multiplicamos valores de 64 bits necesitamos incluir un factor adicional de 10.000 para compensar el factor de escala del 0,0001.
Multiplicar: C3 = (C1 * 10000) * C2
Dividir: C3 = (C1 / C2) / 10000

NOTA: Los paréntesis están puestos para conservar toda la precisión que sea posible aunque se incrementa la posibilidad de desbordamiento (overflow).

Si estamos usando valores de 32 bits debemos convertirlos a y de 64 bits como se comentó anteriormente.

Multiplicar y dividir por un escalar.
Cuando multiplicamos o divimos por una cantidad escalar (byte, integer, long) no necesitamos hacer el ajuste de escala.
Multiplicar: C2 = C1 * 24
Dividir: C2 = C1 / 3

NOTA: Si estamos usando valores de 32 bits debemos convertirlos a y de 64 bits.

Aplicación de ejemplo.
El siguiente ejemplo mostrará :
- Cómo convertir valores de 32 bits en valores de 64 bits.
- Cómo convertir valores de 64 bits en valores de 32 bits.
- Cómo sumar dos pares de valores de 32 bits obteniendo un par de valores de 32 bits.

Creamos un nuevo proyecto y añadimos un formulario (Form1) y un CommandButton (Command1).

Añadimos el siguiente código en Form1 :


      Option Explicit

      Private Type MungeCurr
        Value As Currency
      End Type

      Private Type Munge2Long
        LoValue As Long
        HiValue As Long
      End Type

      Private Function TextToCurr(ByVal Value As String) As Currency
      Dim L As Long, Negative As Boolean
        Value = Trim$(Value)
        If Left$(Value, 1) = "-" Then
          Negative = True
          Value = Mid$(Value, 2)
        End If
        L = Len(Value)
        If L < 4 Then
          TextToCurr = CCur(IIf(Negative, "-0.", "0.") & _
                            Right$("0000" & Value, 4))
        Else
          TextToCurr = CCur(IIf(Negative, "-", "") & _
                            Left$(Value, L - 4) & "." & Right$(Value, 4))
        End If
      End Function

      Private Function CurrToText(ByVal Value As Currency) As String
      Dim Temp As String, L As Long
        Temp = Format$(Value, "#.0000")
        L = Len(Temp)
        Temp = Left$(Temp, L - 5) & Right$(Temp, 4)
        Do While Len(Temp) > 1 And Left$(Temp, 1) = "0"
          Temp = Mid$(Temp, 2)
        Loop
        Do While Len(Temp) > 2 And Left$(Temp, 2) = "-0"
          Temp = "-" & Mid$(Temp, 3)
        Loop
        CurrToText = Temp
      End Function

      Private Sub Command1_Click()
      Dim C1 As MungeCurr, C2 As MungeCurr, C3 As MungeCurr
      Dim L As Munge2Long
      ' Convertimos un valor de 64 bits en dos de 32 bits.
        C1.Value = TextToCurr("123456789012345678")
        LSet L = C1
        Debug.Print CurrToText(C1.Value) & " => (" & L.HiValue & "," & _
                    L.LoValue & ")"

      ' Convertimos dos valores de 32 bits en uno de 64 bits.
        L.HiValue = -1
        L.LoValue = -1
        LSet C1 = L
        Debug.Print "(" & L.HiValue & "," & L.LoValue & ") => " & _
                    CurrToText(C1.Value)

      ' Suumamos dos pares de valores de 32 bits para obtener un par de
      ' valores de 32 bits.
        L.HiValue = 33333333
        L.LoValue = 44444444
        LSet C1 = L
        L.HiValue = -22222222
        L.LoValue = 11111111
        LSet C2 = L
        C3.Value = C1.Value + C2.Value
        LSet L = C3
        Debug.Print "(33333333,44444444) + (-22222222,11111111) => (" & _
                    L.HiValue & "," & L.LoValue & ")"
      End Sub


Ejecutamos el proyecto y pulsamos sobre el CommandButton.

RESULTADO: Debemos obtener los siguientes resultados en la ventana de debug :

123456789012345678 => (28744523,-1506741426)
(-1,-1) => -1
(33333333,44444444) + (-22222222,11111111) => (11111111,55555555)



Trucos Trucos

Visual Basic Página de Visual Basic

Página principal Página principal

www.jrubi.com