Pb pour initialiser un entier Long par un calcul

[Résolu]
Signaler
Messages postés
12
Date d'inscription
mercredi 21 janvier 2004
Statut
Membre
Dernière intervention
30 mai 2008
-
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
-
Bonjour,

Chais pas trop quel titre évocateur utiliser pour expliquer le pb :

Dim lngTest as Long
lngTest = 300 * 200
ou n'importe quel calcul dont le résultat est supérieur à la limite des Integer soit 32 767
entraîne le message "erreur d'exec 6. dépassement de capacité"

Autre exemple encore plus tordu :
Dim lngTest as Long, intTest2 as Integer
intTest2 = 300
lngTest = intTest2 * 200
plante également !

Au contraire, les codes suivants ne posent pas de pb :

Dim lngTest as Long
lngTest = 50000 * 200

pas plus que
Dim lngTest as Long, lngTest2 as long
lngTest = 300
lngTest2 = lngTest * 200

ou que
Dim lngTest as Long, intTest2 as Integer
intTest2 = 300
lngTest = intTest2 * 40000

Tout se passe comme si lorsque les facteurs du calcul sont :
- des variables explicitement Integer,
- des valeurs numériques implicitement Integer (<32767) !
il évalue le résultat en Integer avant de le passer à la variable résultat quelque soit son type et donc plante si trop grand

Ce qui est fort, c'est que je ne m'en suis jamais aperçu jusqu'à ce jour ! (et donc peut-être suis en train de découvrir l'eau tiède)

Soit j'ai eu trop de la chance, soit c'est dépendant du hard ?

Qui a 1 mn pour tester ce truc et me dire si ça plante aussi chez lui et pourquoi ?

7 réponses

Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
46
salut

problème :
Dim lngTest as Long
lngTest = 300 * 200

solution :
VB voit 300 et 200
il se dit entier et entier... beh c'est entier (espace de travail)
mais 60000>entier, donc boom

il faut qu'au moins un des 2 soit plus grand

Dim lngTest As Long
lngTest = CLng(300) * 200
long et entier : espace de travail = long. là c'est bon

idem pour
Dim lngTest as Long, intTest2 as Integer
intTest2 = 300
lngTest = intTest2 * 200

entier et entier, çà n'ira pas....

Dim lngTest as Long, intTest2 as Integer
intTest2 = 300
lngTest = intTest2 * 200&

là çà marche ;)

++
<hr size="2" width="100%" />Prenez un instant pour répondre à [infomsg_SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp
Messages postés
12
Date d'inscription
mercredi 21 janvier 2004
Statut
Membre
Dernière intervention
30 mai 2008

J'avais bien diagnostiqué cette histoire !
"il se dit entier et entier... beh c'est entier (espace de travail)"

J'ai toujours pensé : lngTest = ... donc j'alloue un espace de travail pour un Long puisque de toute façon même si le résultat est petit je consommerai 4 octets ...
C'est du gagne petit !
D'autant + fort que généralement MS ne se préoccupe pas trop d'économiser de la mémoire !

C'est assez pervers (et trop laid ...).
Je ne comprends toujours pas comment mes programmes n'ont jamais planté jusqu'à ce jour !
J'ai eu trop de bol !

Tout le monde sait-il ça et je suis un des derniers grands naïfs subsistants ?
Est-ce que le même phénomène survient avec d'autres langages que VB ?
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
46
je sais pas si c'est su mais je sais qu'c'est çà
(jolie allitération non ? :p)

et idem pour dotnet oui, et très logiquement aussi pour d'autres langages....

autant matériellement (supposais-tu), la question ne se pose à ma connaissance que pour les doubles (si ce n'est TOUS les types à 'virgule flottante')
intel contre le reste du monde ^^

nb : le integer étant le plus souvent utilisé pour des incréments ou des calculs simples (+ -), on a rarement le "faux bug", les long/double sont préférés pour les autres calculs

++
<hr size="2" width="100%" />Prenez un instant pour répondre à [infomsg_SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp
Messages postés
12
Date d'inscription
mercredi 21 janvier 2004
Statut
Membre
Dernière intervention
30 mai 2008

Merci !
Messages postés
7741
Date d'inscription
mercredi 1 septembre 2004
Statut
Membre
Dernière intervention
24 septembre 2014
40
Petite précision sur les variables et leur place en mémoire.

VB6 fonctionne sur la plateforme Win32 ou l'unité de base est le 32bit. Toutes les variables déclarées en VB6 dont la taille est inférieure à 32bit occuperont tout de même 32 bits en mémoire. C'est le cas pour le Long, l'Integer, le Byte. C'est une question d'alignement mémoire.
VB6 ne dispose pas de mécanisme d'optimisation comme certains langages plus évolués qui permettrait par exemple de regrouper 4 bytes dans un emplacement mémoire.
C'est totalement transparent pour l'utilisateur dans 99.99% des cas, mais ça peut etre génant dans certains cas de traitements biens particulier.

Pour ce qui est de ton calcul, le fonctionnement est très simple.
VB analyse ta formule, détermine le premier opérande ainsi que son type, il en déduit que ce sera le type du résultat.
Il analyse le second opérande et tente de le convertir au type du premier (et donc du résultat).
Ensuite il fait l'opération et obtient le résultat.

Ce n'est qu'une fois obtenu ce résultat, qu'il analyse le type de la variable devant recevoir ce résultat, tente de convertir ce résultat, et afin attribu cette convertion à la variable.

D'où l'effet de bord que tu viens de rencontrer.

Par exemple :tu dis que lngTest2 lngTest * 200  c'est vrai. Par contre lngTest2 200 * lngTest  ne doit normalement pas marcher, alors que le résultat est strictement le même

---- Sevyc64  (alias Casy) ---- <hr size ="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #    http://aide-office-vba.monforum.com/index.php
Messages postés
12
Date d'inscription
mercredi 21 janvier 2004
Statut
Membre
Dernière intervention
30 mai 2008

C'est violent ce que tu dis Casy.

Du coup, à quoi ça sert d'utiliser des integer ou des byte s'ils occupent autant de memoire qu'un Long ? 

Dans le fond à quoi servent ces types ? ... !
Seules les distinctions Single/Double et Long/Decimal conservent un intérêt.
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Modérateur
Dernière intervention
3 février 2018
46
salut Casy,
ton exemple est incorrect : VB ne converti pas de gauche à droite mais "au mieux"
lngTest2 = 200 * lngTest  marchera

quant au "pourquoi faire alors", on manque sans doute d'infos.
il serait réducteur (j'espère en tout cas) de penser "types existants par habitude pour les dev".
cependant il me semble bien qu' rt15 s'était amusé à faire certains tests (asm je crois) qui démontraient au final que le byte (par exemple) ne prenait pas vraiment ces 32 bits....

il faudrait des années pour retrouver le sujet   , bien dommage...
si l'un de vous veut tenter de le contacter, il a peut-être encore le lien ;)

++
<hr size ="2" width="100%" />Prenez un instant pour répondre à [infomsg_SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp