tag descripcion integer long-integer integer-overflow vba

integer - descripcion - ¿Por qué usar entero en lugar de largo?



meta title y meta descripcion (7)

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 long ?

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 un impacto en el rendimiento o alguna otra cosa que dicte que no se use long ?


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

msdn

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

msdn

Entonces, el beneficio está en un espacio de memoria reducido. Un número entero ocupa la mitad de la memoria que un largo hace. Ahora, estamos hablando de 2 bytes, por lo que no va a hacer una diferencia real a menos que esté almacenando una TONELADA de enteros.

PERO en un sistema de 32 bits, un entero de 16 bits se convierte silenciosamente en un largo sin el beneficio del mayor rango de números para trabajar. Todavía se producen desbordamientos y se necesita la misma cantidad de memoria. El rendimiento incluso puede verse afectado porque el tipo de datos debe convertirse (a un nivel muy bajo).

No es la referencia que estaba buscando pero ...

Tengo entendido que el motor VB subyacente convierte enteros en largos incluso si se declara como un entero. Por lo tanto, se puede observar una ligera disminución de la velocidad. He creído esto por algún tiempo y quizás por eso también se hizo la declaración anterior, no pedí razonamiento.

foros de ozgrid

Esta es la referencia que estaba buscando.

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

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

Obviamente -1 no es igual a 65535 pero la computadora está devolviendo 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 es mayor que 32k es automáticamente un largo)

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

"FFFFFFFF" = "FFFF"

En general, no tiene sentido que VBA declare "As Integer" en los sistemas modernos, excepto quizás por algunas API heredadas que esperan recibir un Integer.

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 contener números pequeños, ya que requieren menos memoria. Sin embargo, en versiones recientes, VBA convierte todos los valores enteros a tipo Long, incluso si se declaran como tipo Integer. Por lo tanto, ya no hay una ventaja de rendimiento al usar variables enteras; de hecho, las variables largas pueden ser un poco más rápidas porque VBA no tiene que convertirlas.

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 antigua llamada de API que espera un int de 16 bits.

Una cosa que vale la pena señalar es que algunas funciones API antiguas pueden esperar parámetros que son enteros de 16 bits (2 bytes) y si está en un bit de 32 y está tratando de pasar un entero (que ya tiene una longitud de 4 bytes) por referencia no funcionará debido a la diferencia en la longitud de bytes.

Gracias a Vba4All por señalar eso.


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 )

Long tuvo el mejor desempeño, así que tengo que pensar que la recomendación de Microsoft de usar siempre Long 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

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


Como otros ya mencionaron, un Long puede ocupar el doble de espacio que un Integer . Como otros también ya mencionaron, la alta capacidad de las computadoras actuales significa que no verá ninguna diferencia en el rendimiento , a menos que esté tratando con cantidades extra extra extra de datos:

Memoria

Considerando 1 millón de valores , la diferencia entre usar números enteros versus largos sería de 2 bytes para cada valor, por lo que es 2 * 1 000 000 / 1,024 / 1024 = menos de 2 MB de diferencia en su RAM , lo que probablemente sea mucho menor que 1% o incluso 0.1% de su capacidad de RAM.

Tratamiento

Teniendo en cuenta el punto de referencia realizado por PGSystemTester''s, puede ver una diferencia de 811 - 745 = 66 segundos entre Longs y Integers, al procesar 10 mil millones de lotes de 4 operaciones cada uno. Reduzca el número a 1 millón de operaciones y podemos esperar 66/10 000/4 = menos de 2 ms de diferencia en el tiempo de ejecución .

Personalmente uso números enteros y largos para ayudar a la legibilidad de mi código , particularmente en los bucles, donde un entero indica que se espera que el bucle sea pequeño (menos de 1000 iteraciones), mientras que un Long me dice que se espera que el bucle sea bastante grande (más de 1000).

Tenga en cuenta que este umbral subjetivo está muy por debajo del límite superior de Integer, uso Longs solo para hacer la distinción entre mis propias definiciones de pequeño y grande.


Como se señaló en otras respuestas, la diferencia real 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 para recordar sobre esto es que los tipos de datos difieren tanto por idioma como por sistema operativo / plataforma. En su mundo de VBA, un largo es de 32 bits, pero en c # en un procesador de 64 bits, un largo 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 usar 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.


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 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.


Tomé el método de @ PGSystemTester y lo actualicé para eliminar alguna variabilidad potencial. Al colocar el bucle en las rutinas, esto elimina el tiempo necesario para llamar a la rutina (que es mucho tiempo). También he desactivado la actualización de pantalla para eliminar cualquier retraso que esto pueda causar.

Long aún obtuvo el mejor rendimiento, y dado que estos resultados se limitan más estrechamente a los impactos de los tipos de variables solos, vale la pena señalar la magnitud de la variación.

Mis resultados (escritorio, Windows 7, Excel 2010):

Código usado:

Option Explicit Sub VariableOlympics() ''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 Dim chosenWorksheet As Worksheet Set chosenWorksheet = ThisWorkbook.Sheets("TimeTrialInfo") Application.EnableEvents = False Application.Calculation = xlCalculationManual Application.ScreenUpdating = False trials = 1000000000 '' 1,000,000,000 - not 10,000,000,000 as used by @PGSystemTester p = 0 beginTIME = Now boomBYTE trials Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2") p = p + 1 beginTIME = Now boomINTEGER trials Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2") p = p + 1 beginTIME = Now boomLONG trials Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2") p = p + 1 beginTIME = Now boomDOUBLE trials Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2") p = p + 1 beginTIME = Now boomUNDECLARED trials Finished p, Now - beginTIME, CDbl(trials), chosenWorksheet.Range("B2") p = p + 1 Application.EnableEvents = True Application.Calculation = xlCalculationAutomatic Application.ScreenUpdating = True chosenWorksheet.Calculate End Sub Private Sub boomBYTE(numTrials As Long) Dim a As Byte, b As Byte, c As Byte Dim i As Long For i = 1 To numTrials a = 1 b = 1 + a c = 1 + b c = c + 1 Next i End Sub Private Sub boomINTEGER(numTrials As Long) Dim a As Integer, b As Integer, c As Integer Dim i As Long For i = 1 To numTrials a = 1 b = 1 + a c = 1 + b c = c + 1 Next i End Sub Private Sub boomLONG(numTrials As Long) Dim a As Long, b As Long, c As Long Dim i As Long For i = 1 To numTrials a = 1 b = 1 + a c = 1 + b c = c + 1 Next i End Sub Private Sub boomDOUBLE(numTrials As Long) Dim a As Double, b As Double, c As Double Dim i As Long For i = 1 To numTrials a = 1 b = 1 + a c = 1 + b c = c + 1 Next i End Sub Private Sub boomUNDECLARED(numTrials As Long) Dim a As Variant, b As Variant, c As Variant Dim i As Long For i = 1 To numTrials a = 1 b = 1 + a c = 1 + b c = c + 1 Next i End Sub Private Sub Finished(i As Long, timeUSED As Double, trials As Double, initialCell As Range) With initialCell.Offset(i, 0) .Value = trials .Offset(0, 1).Value = timeUSED .Offset(0, 2).FormulaR1C1 = "=ROUND(RC[-1]*3600*24,2)" End With End Sub


VBA tiene mucho equipaje 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.