Problème de conditions

Résolu/Fermé
_rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015 - Modifié par pijaku le 7/07/2015 à 10:38
_rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015 - 7 juil. 2015 à 19:56
Bonjour à tous,

Je vous contacte aujourd'hui car je me prends la tête sur un problème depuis deux jours et que je ne comprends pas mon erreur.

Je travaille actuellement sur un gros projet VBA, j'ai donc un projet avec plusieurs feuilles et des UserForms, mais aussi des modules.

Dans un des modules je fais appel à deux fonctions Min et Max qui me renvoient le minimum et la maximum d'une série de nombres dans une de mes feuilles Excel:
Modules: Max_Min:
Function Min(curseur As Integer, n As Integer) As Double

End Function

Function Max(curseur As Integer, n As Integer) As Double

End Function


Dans mon autre module, j'appelle ces fonctions:
Modules: Enregistrer_Isole:
Sub Enregistrer(curseur As Interger)
      Dim Maximum As Double
      Dim Minimum As Double

     Minimum = Max_Min.Min(curseur,4)
     Maximum = Max_Min.Max(curseur,4)

     If Maximum - Minimum <= 0.1 Then
     ...
     End If
End Sub


Mon problème est que lorsque Maximum - Minimum=0.1, mon programme ne rentre pas dans la condition If alors qu'il rentre bien lorsque la soustraction < 0.1.

J'ai tout essayé: j'ai mis la soustraction dans une variable, j'ai séparé mon if en If(Maximum-Minimum = 0.1 OR Maximum - Minimum < 0.1)...

Aucune des choses que j'ai tentée n'a marché. En sachant que pour tester j'ai créé une variable dans mon Sub, égale à 0.1 et cela à marché:
Sub Enregistrer(curseur As Interger)
      Dim Variable As Double

    Variable = 0.1

     If Variable <= 0.1 Then
     ...
     End If
End Sub


Pour finir j'ai comparé le type des variables entre elles et j'ai bien une variable double pour la soustraction de Maximum-Minimum et une double de même valeur pour ma variable Variable.

Voila mon problème, j'espère ne pas avoir été trop long et ne pas vous avoir perdu.

Merci d'avance pour les réponses.

1 réponse

DevAxia Messages postés 34 Date d'inscription jeudi 25 juin 2015 Statut Membre Dernière intervention 18 novembre 2015 2
7 juil. 2015 à 14:59
Bonjour,
Tout d'abord, petit conseil, tu pourrais utiliser les fonctions du tableur Excel pour tes maximums et minimums
Ex: Application.WorksheetFunction.Min(curseur, 4)

Pour ce qui est de ta situation, le premier problème que je vois est que tu utilises des Integer (entiers) comme paramètres de tes fonctions Min, Max et Enregistrer. Donc même si tu passe une valeur avec des décimales à ces fonctions, elles ne seront pas prises en compte (4.1231 deviendra 4 en entrant dans la fonction).

Il est donc impossible que la soustraction de tes résultats des deux fonctions prenant seulement des entiers (et retournant automatiquement des entiers), ne te donne un résultat = 0.1.

Pat
DevAxia
0
_rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015
7 juil. 2015 à 15:13
Bonjour,

Et tout d'abord merci de ta réponse. Merci du conseil pour le min et max ;)
Pour ton commentaire je ne suis pas d'accord, ou alors c'est que je n'ai pas compris les types d'une fonction. Mais les entiers que je passe dans ma fonction me permettent seulement de faire varier des boucles for qui sont dans mes fonctions, sinon je renvoie bien un double en notant: function min( as integer, as integer) As double. Pour moi la valeur renvoyée est un double car ma fonction est en As Double.

Maintenant j'ai réussi à corriger mon problème mais je ne comprends pas pourquoi ça marche. En fait j'ai crée une variable Single et ça a marché:
Sub Enregistrer_4_Isole(curseur As Integer)
Dim dif As Single
Dim maximum_4 As Double
Dim minimum_4 As Double


maximum_4 = Max_Min.maximum(curseur, 4)
minimum_4 = Max_Min.minimum(curseur, 4)
dif = maximum_4 - minimum_4

If dif <= 0.1 Then
...
End If
End Sub

Ce programme marche et je ne sais pas pourquoi en mettant la différence dans un single la condition fonctionne.
Je pense que ça un rapport avec ton commentaire et que mes types ne sont pas juste mais je ne comprends pas pourquoi car mes paramètres de fonctions sont seulement utilisés pour des boucles for au sein des fonctions.

Serais-tu pourquoi ça marche avec un Single?
0
DevAxia Messages postés 34 Date d'inscription jeudi 25 juin 2015 Statut Membre Dernière intervention 18 novembre 2015 2 > _rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015
7 juil. 2015 à 15:33
Ok, désolé pour la confusion sur les Integer qui servent aux boucles For, aucun problème de ce côté alors.

Alors ton problème est un niveau plus loin, voilà la réponse, et même si ça marche avec ton single, je ne suis pas convaincu que ça marchera toujours...

Le problème est dans la représentation des nombres à point flottant (floating point numbers) de type Single ou Double. En réalité, il n'est pas adéquat de comparer deux valeurs Double avec une égalité, à cause de la nature de la représentation de ces nombres, qui sont représentés avec une mantisse et un exposant (je n'entre pas plus dans les détails, mais cette méthode permet des nombre de très grande précision).

Une valeur de 0.1 pourrait tout aussi bien être représentée à l'intérieur de la mémoire comme 0.099999999999827 ou 0.10000000001218. Mais pour toi, elle apparaîtrait comme 0.1.

En comparant deux nombres Double en égalité, tu compares peut-être
If 0.099999999999827 = 0.10000000001218 Then


La solution est d'arrondir les nombres que tu veux comparer
Comme par exemple..
If Round(Maximum, 2) - Round(Minimum, 2) <= 0.1 Then


En utilisant un Single, c'est un peu ce que tu as fait, mais de façon un peu invisible, vu que le Single est moins précis que le Double, il arrondi le résultat et arrive assez près de ta valeur de comparaison 0.1, mais c'est un risque, deux autres valeurs pourraient ne pas fonctionner.

Pat
DevAxia
0
_rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015
7 juil. 2015 à 15:45
Ahhhh d'accord ta réponse explique tout, merci mille fois.
Et c'est pour ça que autre part dans mon code j'ai un problème, je fais des soustractions de double et par exemple: valeur_Absolue(1,45 - 1,38) = 0,07000005 et non pas 0,07 comme je l'attends car derrière je mets une condition:: if valeur_Absolue <= 0,07.

Je comprends mieux mes erreurs alors, je vais donc devoir arrondir toutes mes valeurs pour être sur qu'elle soit juste.

Merci encore ;)

Petit dernier conseil, tu me conseilles de mettre tout en double ou en Single. De toute façon j'utiliserai la fonction arrondie mais c'est juste pour ne plus commettre des erreurs comme ça?
0
DevAxia Messages postés 34 Date d'inscription jeudi 25 juin 2015 Statut Membre Dernière intervention 18 novembre 2015 2 > _rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015
7 juil. 2015 à 16:35
Les Single utilisent 4-bytes (4-octets ou 32-bits) de précision alors que les Double utilisent 8-bytes (8-octets ou 64-bits), le double...

Ça dépend de la précision que tu as besoin, les Double prennent donc le double de la mémoire, et très souvent, les Single sont largement suffisants, mais souvent aussi, par défaut, on utilise les Double. Si tes ressources mémoires et le processing est peu important surtout.

Les Singles:
entre -3,402823E38 et -1,401298E-45 pour les valeurs négatives
entre 1,401298E-45 et 3,402823E38 pour les valeurs positives

Les Doubles:
entre -1,79769313486231E308 et -4,94065645841247E-324 pour les valeurs négatives
entre 4,94065645841247E-324 et 1,79769313486232E308 pour les valeurs positives

Pat
DevAxia
0
_rettt Messages postés 17 Date d'inscription mardi 7 juillet 2015 Statut Membre Dernière intervention 23 juillet 2015
7 juil. 2015 à 16:41
Ok merci beaucoup, je vais utiliser les Single alors.

Merci poour tes conseils, tu m'as fortement aidé.

Bonne fin de journée à toi
0