Saut de If à Else malgré condition vérifiée

Résolu/Fermé
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011 - 19 févr. 2009 à 03:11
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011 - 20 févr. 2009 à 16:22
Bonjour à Toutes et à Tous,
et bien entendu un GRAND MERCI à toutes celles et à ceux qui nous rendent de fiers services en répondant à nos questions de tous niveaux grâce à CCM.


Je programme actuellement en VBA un petit fichier pour gérer mes dépenses.

Seulement voilà, avant d'écrire dans la dernière cellule de mon tableau, j'ai besoin de vérifier l'égalité entre deux sommes de cellules différentes

Plus précisément l'égalité entre la somme des cellules de la dernière colonne de mon tableau et
et la somme des cellules de la dernière ligne du même tableau

Dim Total_A as Double
Dim Total_B as Double

Total_A = la première somme
Total_B = la seconde somme

If Total_A = Total_B Then
j'écris dans ma dernière cellule
Else
je fais autre chose
End if


ET VOICI LE PROBLEME!!!
Les valeurs de Total_A et Total_B sont rigoureusement identiques (-663.36 dans mon cas) donc Total_A = Total_B
et pourtant la macro passe directement à Else comme si ma condition Total_A = Total_B n'était pas vérifiée.

J'ai même taper les sommes sur ma calculette, elles sont justes, strictement identiques ET sans arrondi.

Est-ce que quelqu'un à déjà été confronté à ce problème?
Existe-t-il un moyen de forcer VBA à nous indiquer les différences qu'il trouve entre mes variables?


Pour les puristes, voici mon bout de code qui déconne:
(les variables i et col sont parfaitement renseignées)


'Total_A = Somme colonne 14
Total_A = Application.WorksheetFunction.Sum(Range(Cells(5, col), Cells(i, col)))

'Total_B = Somme ligne i+1
Total_B = Application.WorksheetFunction.Sum(Range(Cells(i + 1, 2), Cells(i + 1, 13)))

If Total_A = Total_B Then
ActiveSheet.Cells(i + 1, col).Value = Total_A
Else
ActiveSheet.Cells(i + 1, col).Value = "ERREUR"
End If

Personnellement, je n'y comprends plus rien, les valeurs à comparer (-663.36) sont assez simples avec très peu de caractères.
Lors de l'exécution, j'ai placé un espion sur mes deux variables.
Les valeurs sont rigoureusement les mêmes et sont obtenues avec aucune approximation.
Il n'y a en apparence, AUCUNE raison de ne pas rentrer dans la boucle If.


J'espère que vous arriverez à voir ce qui m'échappe, car je suis complètement désarmé devant ce problème.
VBA serait-il en panne au point de ne plus pouvoir gérer correctement une If?


Merci d'avoir lu jusqu'au bout, vous n'avez pas perdu votre temps.... Ou pas, faut voir....

10 réponses

Rien ne t'empêche d'afficher les 2 valeurs avant le test;
Et puis il faut faire attention à une chose... la machine travaille en binaire, rien de surprenant mais un problème sournois se pose quand on a des décimales.
Un exemple:
10,8 en décimal c'est 10 plus exactement 4/5 mais pas en binaire... eh oui 10 c'est dix mais 0.8 ne sera qu'une approximation de sommes de 2 puissance -1, 2 puissance -2, 2 puissance -3.... (0,8 c'est 0,5 + 0,25 + 0,03125 + ...) si bien que 0.8 traduit en binaire ne sera pas exact et si l'on fait '11 - 10,8' en décimal on a un résultat approximatif de 0,2 en binaire, ce je veux dire c'est que d'approximation en approximation, on peut arriver à avoir A=1,999 et B=1,998.
Ai-je été clair?
3
Bidouilleu_R Messages postés 1181 Date d'inscription mardi 27 mai 2008 Statut Membre Dernière intervention 12 juillet 2012 288
19 févr. 2009 à 07:08
bonjour,
moi j'aimerai bien savoir
le contenu de :

'Total_A = Somme colonne 14
Total_A = Application.WorksheetFunction.Sum(Range(Cells(5, col), Cells(i, col)))

'Total_B = Somme ligne i+1
Total_B = Application.WorksheetFunction.Sum(Range(Cells(i + 1, 2), Cells(i + 1, 13)))
est-ce que le débbogueur affiche la même valeur.
un format d'affichage pourrait masquer une différence minime mais ne remplirai pas la condition.
genre : 1.999 (2.00 affiché)
2
Je n'ai pas beaucoup écrit en VBA et il y a bien longtemps.
Au lieu du code suivant:
Dim Total_A as Double
Dim Total_B as Double

Total_A = la première somme
Total_B = la seconde somme

If Total_A = Total_B Then
j'écris dans ma dernière cellule
Else
je fais autre chose
End if
J'essaierai
Dim Total_A as Double
Dim Total_B as Double

Total_A = la première somme
Total_B = la seconde somme
Total_A = Total_B

If Total_A = Total_B Then
j'écris dans ma dernière cellule
Else
je fais autre chose
End if
Evidemment 'Total_A = Total_B' parait absurde mais j'aimerai bien savoir si on passe dans le 'if' ou dans le 'else'; moi je parie pour le 'if' car j'ai plutôt confiance, par principe, dans le logiciel.
1
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
20 févr. 2009 à 09:51
Sinon, il y a la solution utiliser en calcul scientifique. Nous ne faisons jamais de test d'égalité mais :
if valeur_absolu(A-B)<tolérance
dans ton cas, tu prends une valeur de tolérence de 0,01
1
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
20 févr. 2009 à 16:22
Ouai c'est pas faux :)

Ca aussi, j'en prends note........
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
19 févr. 2009 à 08:31
connait pas VBA, mais je trouve étrange que le signe d'affectation soit le même que celui de comparaison.
en C: a=b; if(a==b);
en Fortran: a=b if(a.eq.b)
en pascal: a:=b if a=b
0
Bidouilleu_R Messages postés 1181 Date d'inscription mardi 27 mai 2008 Statut Membre Dernière intervention 12 juillet 2012 288
19 févr. 2009 à 08:58
l'écritue est juste le VBA.
Le VB n'est pas aussi "stricte" ou rigoureux que pascal, C, ou python...
mais on ne fait pas la même chose non plus.
0
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
19 févr. 2009 à 18:28
Waw, tant de réponses en si peu de temps !!!!!
C'est sympa, je me sens moins seul ;)
Merci à Tous

Je viens d'essayer la technique de Loupious,
c'est à dire taper

Dim Total_A as Double
Dim Total_B as Double

Total_A = la première somme
Total_B = la seconde somme

Total_A = Total_B

If Total_A = Total_B Then
j'écris dans ma dernière cellule
Else
je fais autre chose
End if



Je suis rassuré de voir que la macro rentre bien dans la If et pas dans la Else!

Ce qui prouve que la macro trouve bien deux résultats différents pour Total_A et Total_B

Cependant, voici les valeurs que j'additionne :

Total_A :
-764.78
101.42
0
0
0
0
0
0
0
0
0
0


Total_B :
0
-34.1
-3876.82
-263.2
-165.18
-19.24
-25
0
0
0
-590
315
0
-170
-34.82
700
3500

Faites donc le calcul, le résultat des deux sommes sont identiques et bien égaux à -663.63
Nul besoin d'approximation pour atteindre ce résultat.

Si VBA trouve un résultat différent, c'est qu'il ne sait pas faire une simple addition, et c'est grave!!!!


Vous trouverez ici un zip contenant 3 captures d'écran qui montrent ce que fait la macro avec en bas des images les valeurs indiquées par le débogger.

http://destmobil.neuf.fr/Pb_macro_VBA.zip



Donc, au risque de me répéter et étant donné que la macro considère que mes variables ne sont pas égales,
existe-t-il un moyen de forcer VBA à indiquer les différences entre les deux variables qui m'intéressent?


Personnellement, je suis sur le cul !!!!
Sidéré de buter sur ce problème avec des valeurs aussi simples...
Si les valeurs que j'additionne avaient une infinité de décimales, je comprendrais facilement qu'un problème d'arrondi peut arriver....
Mais là!!!!!!!!!!!!!!!!!

Je n'ai jamais plus de 2 décimales et une addition ne peut pas créer de décimales supplémentaires. C'est mathématiquement impossible!!!!
Ce serait absurde d'avoir un résultat du genre -663.62999999999999999999999 !

Bref,

Au Secouuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuurs

:o)
0
lermite222 Messages postés 8702 Date d'inscription dimanche 8 avril 2007 Statut Contributeur Dernière intervention 22 janvier 2020 1 190
19 févr. 2009 à 19:25
Bonjour tous,
Les montants que tu donne en exemple sont-il le contenu de cellules ?
Et tes données arrivent d'un fichier texte ?
Si oui...
Quand tu met un texte -34.1 dans une cellule il n'est plus possible de le comptabilisé ni de changer le format.
Seule solution, Changer manuellement le Point par une virgule ou si beaucoup de données faire une macros pour changer le point.
Et les résultat A et B ne SONT PAS IDENTIQUE
A= -663,36000
B= -2568,12
A+
0
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
19 févr. 2009 à 23:59
T'as dû faire une faute de frappe en calculant B......
Moi je trouve bien -663.36 pour A et pour B, et ce, que j'utilise excel, ma caltos, ou bien en additionnant à la main.
0
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
19 févr. 2009 à 22:00
Bon et biennn,
m'est avis que Loupius tient le bon bout!

Son explication tient la route et je pense que la solution consiste à traiter le mal par le mal.

C'est à dire, que je vais immédiatement faire en sorte que mes deux variables soient quoiqu'il arrive arrondies au centième.

Ainsi, Total_A et Total_B auront forcément 2 décimales maximum et ma condition Total_A = Total_B sera alors vérifiée!



Sinon j'ai pensé à une seconde solution, multiplier toutes mes valeurs par 100, puis les additionner et enfin comparer les sommes. Je n'aurai ainsi aucun problème de décimale puisque la macro ne verra que des entiers.


Pour répondre à ta question lermite222, les valeurs que je vous ai donné sont exactement celles contenues par les cellules de mon tableau et le Point est le séparateur de décimales sur mon système et Excel les reconnaît bien en tant que valeurs et non en tant que chaînes de caractères. D'autre part, les lignes qui effectuent les additions ne plantent pas (pas d'incompatibilité de type).


Je vous tiens au courant, je pense que ce ne sera pas très long.

A tout à l'heure ;)
0
Multiplier par cent est une solution tentante... mais...
Considérons le nombre 10,8, oui je sais je me répète. Supposons que ce nombre soit 10,79997 en binaire (peut-être 10,79999999999998 en fonction du nombre de bits représentant ce nombre).
Eh bien, que représente 10,8 * 100 en binaire, on peut dire sommairement: 10,79997 * 100 soit 1079,997 qui seront arrondis à 1079 et non pas à 1080. il faut donc faire (10,8 + 0,001) * 100, c'est un problème bien connu.
A méditer
0
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011 > loupius
19 févr. 2009 à 23:46
Euuuuh oui.....

Donc si j'ai bien compris, en binaire, la valeur approximée est toujours légèrement inférieure à la valeur décimale d'origine.

Donc en ajoutant une valeur inférieure à 0,01 à 10,8 (pour reprendre ton exemple), on évite ainsi de se retrouver avec une valeur binaire approximée inférieure à 10,8.

10,801 vaudra en binaire approximativement 10,8009998

On peut alors tranquillement multiplier par 100

STP, dis moi si je me trompe!!!

Je suis bien content que tu ais apporté de telles explications.
J'espère les avoir bien comprises.
0
loupius > Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
20 févr. 2009 à 00:00
J'ai mis 0,001 parce que tu proposais de multiplier par cent; si on multiplie par 1000 il faut mettre moins car on risque d'avoir 1 de plus (il y a quand même des nombres décimaux qui sont justes ( par exemple 0,5 ou 0,75 ou 0,875).
Le problème n'est pas facile à résoudre, c'est une question de calcul des erreurs (du style delta(x * y) = delta (x) + delta (y).
Toutefois il est probable que l'utilisation de la fonction Round() soit satisfaisante.
A tester et bon courage.
0
Destmobil Messages postés 12 Date d'inscription jeudi 19 février 2009 Statut Membre Dernière intervention 28 octobre 2011
19 févr. 2009 à 22:53
YEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHH

Un grand Merci à Tous, vous avez été Super!!!!!!!



L'explication de Loupius est la bonne!!!!!!!!


Même si en apparence il n'y a aucune raison, il se peut que le résultat ne soit pas tout à fait exact à cause des approximations que fait la macro puisqu'elle travaille en binaire.
Attention aux valeurs annoncées par le débogger!!!!!
Visiblement arrondies mais pas utilisées comme telles!




3 solutions différentes pour rentrer enfin dans la If:

--- Grâce à la fonction Round utilisée juste avant d'arriver sur la If
Total_A = Round(Total_A, 2)
Total_B = Round(Total_B, 2)
Syntaxe :Round(expression [,numdecimalplaces])



--- Ou alors en multipliant par 100, mais il faut que les variables soient des Long et plus des Doubles, sinon ça ne marche pas!!!

Dim Total_A as Long
Dim Total_B as Long
Total_A = Application.WorksheetFunction.Sum(Range(Cells(5, col), Cells(i, col))) * 100
Total_B = Application.WorksheetFunction.Sum(Range(Cells(i + 1, 2), Cells(i + 1, 13))) * 100


--- Dernière solution qui fonctionne (mais c'est bizarre)
lorsque les sommes sont calculées directement par des cellules et non par la macro,
la condition Total_A = Total_B est vérifiée.
Probablement parce que les cellules arrondissent d'elle même les valeurs calculées.




Perso, je vais continuer en utilisant la fonction Round(expression, nombre de décimales)
La syntaxe est très simple et il suffit de la placer juste avant de vérifier une condition quelle qu'elle soit.
While, If


Encore une fois Merci à Tous pour votre aide ;)
A bientôt!!!
0