¿Por qué usar números enteros en lugar de largos

vba integer long-integer integer-overflow


A menudo veo preguntas relacionadas con errores de Overflow con vba .

Mi pregunta es ¿por qué usar la declaración de variable integer lugar de solo definir todas las variables numéricas (excluyendo double etc.) long tanto tiempo ?

A menos que esté realizando una operación como en un bucle for donde puede garantizar que el valor no superará el límite de 32,767, ¿hay algún impacto en el rendimiento o alguna otra cosa que dicte que no se use long ?




Answer 1 RubberDuck


Las variables enteras se almacenan como números de 16 bits (2 bytes)

Referencia de Office VBA

Las variables largas (enteros largos)se almacenan como números firmados de 32 bits (4 bytes)

Referencia de Office VBA

Por lo tanto,el beneficio está en la reducción del espacio de memoria.Un entero ocupa la mitad de la memoria que un largo.Ahora,estamos hablando de 2 bytes,por lo que no va a hacer una diferencia real para los enteros individuales,sólo es una preocupación cuando se trata de TONELADAS de enteros (por ejemplo,matrices grandes)y el uso de la memoria es fundamental.

PERO en unsistema de 32 bits, el uso de memoria reducido a la mitad tiene un costo de rendimiento. Cuando el procesador realmente realiza algún cálculo con un número entero de 16 bits (por ejemplo, incrementando un contador de bucle), el valor se convierte silenciosamente en un Long temporal sin el beneficio del mayor rango de números para trabajar. Todavía se producen desbordamientos y el registro que utiliza el procesador para almacenar los valores para el cálculo ocupará la misma cantidad de memoria (32 bits) en ambos sentidos. El rendimiento incluso puede verse afectado porque el tipo de datos debe convertirse (a un nivel muy bajo).

No es la referencia que buscaba,pero...

Mi entendimiento es que el motor VB subyacente convierte los números enteros en largos,incluso si se declara como un número entero.Por lo tanto,se puede observar una ligera disminución de la velocidad.He creído esto durante algún tiempo y tal vez por eso también se hizo la declaración anterior,no pedí un razonamiento.

foros de ozgrid

Esta es la referencia que estaba buscando.

Respuesta corta,en sistemas de 32 bits los enteros de 2 bytes son convertidos en largos de 4 bytes.Realmente no hay otra manera de que los respectivos bits se alineen correctamente para cualquier forma de procesamiento.Considere lo siguiente

MsgBox Hex(-1) = Hex(65535) ' = True

Obviamente -1 no es igual a 65535,pero el ordenador devuelve la respuesta correcta,a saber,"FFFF"="FFFF".

Sin embargo,si hubiéramos forzado el -1 a un largo primero,habríamos obtenido la respuesta correcta (el 65535 siendo mayor que 32k es automáticamente un largo)

MsgBox Hex(-1&) = Hex(65535) ' = False

"FFFFFFFF"="FFFF"

En general,no tiene sentido que la VBA declare "Como Entero" en los sistemas modernos,excepto quizás para algunas API heredadas que esperan recibir un Entero.

foro pcreview

Y por fin encontré la documentación de msdn que realmente estaba buscando.

Tradicionalmente,los programadores de VBA han usado números enteros para mantener los números pequeños,porque requerían menos memoria.Sin embargo,en versiones recientes,VBA convierte todos los valores de los números enteros al tipo Long,incluso si se declaran como tipo Integer.Por lo tanto,ya no hay una ventaja de rendimiento al usar variables de tipo Entero;de hecho,las variables Long pueden ser ligeramente más rápidas porque VBA no tiene que convertirlas.

Para aclarar en función de los comentarios: los enteros aún requieren menos memoria para almacenar: una gran variedad de enteros necesitará significativamente menos RAM que una matriz larga con las mismas dimensiones. Pero debido a que el procesador necesita trabajar con fragmentos de memoria de 32 bits, VBA convierte los números enteros a largos temporalmente cuando realiza los cálculos.


Entonces, en resumen, casi no hay una buena razón para usar un tipo Integer estos días. A menos que necesite interoperar con una llamada API antigua que espera un int de 16 bits, o si está trabajando con grandes conjuntos de enteros pequeños y la memoria es muy importante.

Una cosa que vale la pena señalar es que algunas viejas funciones de la API pueden estar esperando parámetros que son Enteros de 16 bits (2 bytes)y si se está en un 32 bit y se intenta pasar un Entero (que ya tiene una longitud de 4 bytes)por referencia no funcionará debido a la diferencia de longitud de los bytes.

Gracias a Vba4All por señalarlo.




Answer 2 Patrick


Como se ha señalado en otras respuestas,la verdadera diferencia entre int y long es el tamaño de su espacio de memoria y,por lo tanto,el tamaño del número que puede contener.

Aquí está la documentación completa sobre estos tipos de datos http://msdn.microsoft.com/en-us/library/office/ms474284(v=office.14).aspx

un número entero es de 16 bits y puede representar un valor entre -32,768 y 32,767

un largo es de 32 bits y puede representar de -2,147,483,648 a 2,147,483,647

y hay un LongLong que es de 64 bits y puede manejar como 9 pentilion

Una de las cosas más importantes que hay que recordar es que los tipos de datos difieren tanto por el lenguaje como por el sistema operativo/plataforma.En tu mundo de VBA un long es de 32 bits,pero en c#en un procesador de 64 bits un long es de 64 bits.Esto puede introducir una confusión significativa.

Aunque VBA no lo admite, cuando se muda a cualquier otro idioma en .net o java u otro, prefiero utilizar los tipos de datos del sistema de int16 , int32 e int64, lo que me permite ser mucho más transparente sobre los valores que se puede mantener en estos tipos de datos.




Answer 3 Alex K.


VBA tiene mucho bagaje histórico.

Un número Integer tiene 16 bits de ancho y era un buen tipo numérico predeterminado cuando la arquitectura de 16 bits / tamaños de palabra prevalecían.

Un Long tiene 32 bits de ancho y (IMO) debe usarse siempre que sea posible.




Answer 4 PGSystemTester


Aunque esta publicación tiene cuatro años, tenía curiosidad sobre esto y realicé algunas pruebas. Lo más importante a tener en cuenta es que un codificador SIEMPRE debe declarar una variable como ALGO . Las variables no declaradas tuvieron claramente el peor desempeño (las no declaradas son técnicamente Variant es )

Long tuvo el mejor desempeño, así que tengo que pensar que la recomendación de Microsoft de usar siempre Long en lugar de Integer tiene sentido. Supongo que lo mismo es cierto con Byte , pero la mayoría de los codificadores no usan esto.

RESULTADOS EN LA COMPUTADORA PORTÁTIL DE 64 BITS WINDOWS 10

Variable Olympics

Código utilizado:

Sub VariableOlymics()
'Run this macro as many times as you'd like, with an activesheet ready for data
'in cells B2 to D6
Dim beginTIME As Double, trials As Long, i As Long, p As Long

    trials = 1000000000
    p = 0

    beginTIME = Now
    For i = 1 To trials
        Call boomBYTE
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1

    beginTIME = Now
    For i = 1 To trials
        Call boomINTEGER
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomLONG
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomDOUBLE
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1


    beginTIME = Now
    For i = 1 To trials
        Call boomUNDECLARED
    Next i
    Call Finished(p, Now - beginTIME, CDbl(trials))
    p = p + 1

End Sub


Private Sub boomBYTE()
Dim a As Byte, b As Byte, c As Byte

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomINTEGER()
Dim a As Integer, b As Integer, c As Integer

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomLONG()
Dim a As Long, b As Long, c As Long

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomDOUBLE()
Dim a As Double, b As Double, c As Double

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub


Private Sub boomUNDECLARED()

    a = 1
    b = 1 + a
    c = 1 + b
    c = c + 1

End Sub

Private Sub Finished(i As Long, timeUSED As Double, trials As Double)

    With Range("B2").Offset(i, 0)
            .Value = .Value + trials
            .Offset(0, 1).Value = .Offset(0, 1).Value + timeUSED
            .Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,0)"
    End With

End Sub



Answer 5 Alter


Este es un problema de espacio versus necesidad .

En algunas situaciones es necesario usar un largo. Si está recorriendo filas en un archivo de Excel grande, la variable que contiene el número de fila debe ser larga.

Sin embargo, a veces sabrá que un número entero puede manejar su problema y usar un largo sería una pérdida de espacio (memoria). Las variables individuales realmente no hacen mucha diferencia, pero cuando comienzas a tratar con matrices, puede hacer una gran diferencia.

  • En VBA7,los números enteros son 2 bytes y los largos son 4 bytes.

  • Si tiene una matriz de 1 millón de números entre 1 y 10, el uso de una matriz Integer requeriría aproximadamente 2 MB de RAM, en comparación con aproximadamente 4 MB de RAM para una matriz larga.