web-dev-qa-db-fra.com

Pourquoi utiliser Integer au lieu de Long?

Je vois souvent des questions relatives à Overflow erreurs avec vba .

Ma question est la suivante: pourquoi utiliser la déclaration de variable integer au lieu de simplement définir toutes les variables numériques (à l’exclusion de double etc.) comme long?

Sauf si vous effectuez une opération comme dans une boucle for où vous pouvez garantir que la valeur ne dépassera pas la limite de 32 767, existe-t-il un impact sur les performances ou sur quelque chose d'autre qui imposerait de ne pas utiliser long?

57
Gareth

Les variables entières sont stockées sous forme de nombres de 16 bits (2 octets)

msdn

Les variables longues (entier long) sont stockées sous forme de nombres signés 32 bits (4 octets)

msdn

L’avantage est donc de réduire l’espace mémoire. Un entier occupe la moitié de la mémoire d'un long. Maintenant, nous parlons de 2 octets, donc cela ne changera rien si vous ne stockez pas une tonne d'entiers.

[~ # ~] mais [~ # ~] sur un = 32 système de bits, un entier de 16 bits est converti silencieusement en long sans le bénéfice de la plus grande gamme de nombres avec laquelle travailler. Les débordements se produisent toujours et cela prend tout autant de mémoire. La performance peut même être blessée car le type de données doit être converti (à très niveau faible).

Pas la référence que je cherchais mais ....

D'après ce que je comprends, le moteur sous-jacent VB convertit les entiers en long même s'il est déclaré comme un entier. Par conséquent, une légère diminution de la vitesse peut être constatée. Je le crois depuis un certain temps et peut-être aussi pourquoi la déclaration ci-dessus a été faite, je n'ai pas demandé de raisonnement.

forums ozgrid

C'est la référence que je cherchais.

Réponse courte, dans les systèmes 32 bits, les entiers sur 2 octets sont convertis en éléments longs sur 4 octets. Il n'y a vraiment pas d'autre moyen pour que les bits respectifs s'alignent correctement pour toute forme de traitement. Considérer ce qui suit

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

Évidemment, -1 n’est pas égal à 65535, mais l’ordinateur renvoie la bonne réponse, à savoir "FFFF" = "FFFF"

Cependant, si nous avions contraint le -1 à un long début, nous aurions obtenu la bonne réponse (65535 étant supérieur à 32k est automatiquement long)

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

"FFFFFFFF" = "FFFF"

En général, il est inutile dans VBA de déclarer "As Integer" dans les systèmes modernes, sauf peut-être pour certaines API héritées qui s'attendent à recevoir un Integer.

forum pcreview

Et enfin, j'ai trouvé le documentation msdn que je cherchais vraiment.

Traditionnellement, les programmeurs VBA utilisaient des entiers pour contenir de petits nombres, car ils nécessitaient moins de mémoire. Dans les versions récentes, cependant, VBA convertit toutes les valeurs entières en type Long, même si elles sont déclarées en tant que type Integer. Il n’ya donc plus d’avantage en termes de performances pour utiliser les variables Integer; En fait, les variables longues peuvent être légèrement plus rapides car VBA n'a pas à les convertir.

Donc, en résumé, il n’ya presque aucune bonne raison d’utiliser un type Integer de nos jours. Sauf si vous devez interagir avec un ancien appel d'API qui attend un int de 16 bits.

Il convient de souligner que certaines anciennes fonctions de l'API peuvent attendre des paramètres d'entiers 16 bits (2 octets) et si vous utilisez un 32 bits et essayez de passer un entier (celui-ci est déjà long de 4 octets). par référence, cela ne fonctionnera pas à cause de la différence de longueur en octets.

Merci à Vba4All de nous l'avoir signalé.

116
RubberDuck

Comme indiqué dans d'autres réponses, la vraie différence entre int et long est la taille de son espace mémoire et donc la taille du nombre qu'il peut contenir.

voici la documentation complète sur ces types de données http://msdn.Microsoft.com/en-us/library/office/ms474284 (v = office.14) .aspx

un entier représente 16 bits et peut représenter une valeur comprise entre -32 768 et 32 ​​767

a Long correspond à 32 bits et peut représenter -2 147 483 648 à 2 147 483 647

et il y a un LongLong qui est 64 bits et peut gérer comme 9 pentilion

Une des choses les plus importantes à retenir est que les types de données diffèrent par la langue et par le système d’exploitation. Dans votre monde de VBA, 32 bits sont longs, mais en c # sur un processeur 64 bits, 64 bits sont longs. Cela peut introduire une confusion importante.

Bien que VBA ne le supporte pas, lorsque vous passez à une autre langue, que ce soit en .net ou Java ou autre), je préfère de loin utiliser les types de données système de int16 , int32 et int64 , ce qui me permet d’être beaucoup plus transparent sur les valeurs pouvant être conservées dans ces types de données.

12
Patrick

VBA a beaucoup de bagages historiques.

Un Integer a une largeur de 16 bits et était un bon type numérique par défaut lorsque l'architecture et les tailles de mots 16 bits étaient répandues.

Un Long a une largeur de 32 bits et (IMO) doit être utilisé autant que possible.

7
Alex K.

Bien que ce poste date de quatre ans, j'étais curieux à ce sujet et j'ai effectué quelques tests. La chose la plus importante à noter est qu’un codeur devrait TOUJOURS déclarer une variable SOMMAIRE. Les variables non déclarées ont manifestement affiché la pire performance (non déclarées techniquement Variant)

Long a été le plus rapide, je dois donc penser que la recommandation de Microsoft de toujours utiliser Long au lieu de Integer a un sens. Je devine la même chose que true avec Byte, mais la plupart des codeurs ne l'utilisent pas.

RESULTATS SUR ORDINATEUR PORTABLE WINDOWS 10 BITS

Variable Olympics

Code utilisé:

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
6
PGSystemTester

Ceci est un problème espace vs nécessité.

Dans certaines situations, c'est un nécessité d'utiliser un long. Si vous parcourez des lignes dans un fichier Excel volumineux, la variable contenant le numéro de ligne doit être longue.

Cependant, vous saurez parfois qu'un nombre entier peut gérer votre problème et utiliser un long serait un gaspillage de espace (mémoire). Les variables individuelles ne font vraiment pas une grande différence, mais quand vous commencez à manipuler des tableaux, cela peut faire une grande différence.

  • Dans VBA7, les entiers sont 2 octets et longs sont 4 octets

  • Si vous avez un tableau de 1 million de nombres compris entre 1 et 10, utiliser un tableau Integer prendrait environ 2 Mo de RAM, contre environ 4 Mo de = RAM pour un tableau long.

4
Alter

J'ai pris la méthode de @ PGSystemTester et je l'ai mise à jour pour supprimer certaines variabilités potentielles. En plaçant la boucle dans les routines, cela supprime le temps nécessaire pour appeler la routine (ce qui prend beaucoup de temps). J'ai également désactivé la mise à jour de l'écran pour supprimer les retards éventuels.

Long a tout de même obtenu les meilleurs résultats, et comme ces résultats se limitent davantage aux impacts des types de variables uniquement, il convient de noter l'ampleur de la variation.

Mes résultats (bureau, Windows 7, Excel 2010):

enter image description here

Code utilisé:

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
1
AJD

Comme d’autres déjà mentionné, un Long peut occuper deux fois plus d’espace qu'un Integer. Comme d'autres l'ont déjà mentionné, la capacité élevée des ordinateurs actuels signifie que vous verrez aucune différence de performances, sauf si vous traitez des quantités de données extrêmement importantes:

Mémoire

Considérant que 1 million de valeurs, la différence entre utiliser des entiers et des longs serait de 2 octets pour chaque valeur, de sorte que 2 * 1 000 000/1024/1024 = moins de 2 Mo de différence dans votre RAM, qui est probablement beaucoup moins que 1% ou même 0,1% de votre RAM capacité.

En traitement

Si l'on se base sur le repère réalisé par PGSystemTester, vous pouvez constater une différence de 811 à 745 = 66 secondes entre les longueurs longue et entière, lorsque 10 milliards de lots de 4 opérations sont traités. Réduisez le nombre à 1 million d'opérations et nous pouvons nous attendre à 66/10 000/4 = moins de 2 ms de différence de temps d'exécution.


J'utilise personnellement Integer et Longs to lisibilité de mon code, en particulier dans les boucles, où Un entier indique que la boucle devrait être petite (moins de 1000 itérations), alors qu'un long me dit que la boucle est devrait être assez grand (plus de 1000).

Notez que ce seuil subjectif est bien inférieur à la limite supérieure Integer. J'utilise Longs uniquement pour faire la distinction entre mes propres définitions de petit et grand.

0
Ama