Erreur et présions de calcul trop élévée
Hello
J’espère que quelqu'un pourra m'aider car je deviens fou avec ce petit exemple très basique et qui pourtant refuse de fonctionner
Cet exemple devrait incrémenter une cellule à partir de zéro avec un pas de 0,1 et déclencher une réponse différente au moment où la valeur de la cellule deviens égale à 1.
Ci-joint le fichier avec l’exemple:
Private Sub CommandButton1_Click()
dim i as single
i = Range("A1").Value + 0.1
If i < 1 Then Range("A1").Value = i Else Range("A1").Value = 0
end subAu 1er click déjà la cellule donc la valeur était zéro, ne passe pas à 0,1 mais à 0,100000001490116
et finalement après 10 clicks, la valeur de sera jamais strictement égale à 1
- Même en déclarant la variable "as double" ou "as n'importe quoi" etc.
- Même si l'erreur est trop faible pour qu'elle soit lisible à l'affichage, elle existe et ça de fonctionne pas
- Même un "round" ne change rien
- Même en travaillant avec des variables "integer" (en faisaint: x=cellule*10 : x=x+1 : cellule=x/10)
Finalement ma question:
Quelqu'un peut-il me dire pourquoi VBA travail avec 45 décimales si:
0 + 0,1 renvoie 0,100000001490116
Et surtout comment corrigé mon exemple ??
Merci d'avance
Bonjour
Pour moi cette macro fonctionne
Private Sub CommandButton1_Click()
Dim i As Double
i = Range("A1").Value + 0.1
If i < 1 Then Range("A1").Value = i Else Range("A1").Value = 0
End SubPour moi cette macro fonctionne
Merci pour ta réponse mais tu es bien sûr qu'au 10e click la condition "i<1" est bien fausse?
Effectivement en écrivant
dim i as doubleOn ne voit plus l'erreur et ça a l'air de marché mais en réalité l'erreur se situt au delà de la 16e décimal au lieu de la 9e.
Essais ce code là pour remplacer le précédent:
Dim i As Double
i = Range("A1").Value + 0.1
Range("A1").Value = i
If i < 1 Then Range("A2").Value = i - 1 Else Range("A2").Value = "Condition fausse"Chez moi en tout cas, au 10e click, dans la case A2 alors que j’espérais lire"Condition fausse"
Je lis toujours le résultat de i-1 qui n'est pas zéro mais -1,1 E-16 .
Donc ma question reste entière?
Est ce que personne n'aurait boulier qui serait plus efficace que cet ordinateur?
Ou plutôt comment corriger mon exemple?
Bonjour
Petite précision
Ton profil indique XL 2003 et le fichier est au format xls, donc j'ai fait le test sur XL 2003 et pas de souci
Mais ton image correspond à (au moins) XL 2007
J'ai fait le test sur XL 2010 et ..... j'ai le même résultat que toi
Mais cette solution fonctionne
Private Sub CommandButton1_Click()
Dim i As Double
i = Range("A1").Value + 0.1
Range("A1").Value = Round(i, 2)
If i < 1 Then Range("A2").Value = i - 1 Else Range("A2").Value = "Condition fausse"
End SubTu as raison , je me suis planté, j'ai XL 2007
Et tu viens de me donné une raison de plus de le détester !
Pour design c'est Las Vegas mais pour faire 3 lignes de code un commodore 64 ne m'aurait pas causé ces ennuis
En tout cas merci pour le "round", j'avais essayé sans succès!
Finalement l'histoire n'est pas fini! On complique un peu.Voilà un nouvelle exemple
Dans la pratique, je vois un intérêt à ces petites fluctuations de résultats: elle empêche beaucoup de plantage à cause, par exemple, de "division par zéro". Mais dans mon application (qui est bien sûr plus complexe que mes exemples!) ces erreurs parasite mes calculs et me pourrissent la vie.
Const fin As Integer = 100
Dim i As Double, j As Double
Dim text As String
j = 0
For i = 0 To fin Step 0.1
i = Round(i, 1) 'Ligne que je supprime dans le deuxième tableau de l'image
j = j + 1
text = "B" & j
Range(text).Value = i
Next iVoilà le résultat en image:
Colonne A: j'ai tiré manuellement les valeurs
Colonnes B: c'est l'action du programme
En toute logique, les deux colonnes devrait afficher la même chose peu importe la valeur de la constance "fin"
J'ai essayer de deux manière avec et sans la commande "Round" (d'ailleurs arrondir avec 1 décimales c'est quand même une précision nullissime et totalement inacceptable pour mon application mais tant pis!!)
Mais dans les fait, sur 20 essaies seulement 5 me donne les résultats logiquement espérés
Dans les autres le programme s'arrête avec la dernière valeur ou bien donne des valeur fausse après seulement une 60aine d'itérations.
Si Microsoft a jugé utile d'introduire des réactions illogiques dans son logiciel... c'est pour qu'il est l'air plus humain ??!!
Comment programmer quand on ne peut pas prévoir les réactions du système??!!
Pourquoi ces erreurs?
N'y-a-t-il pas un paramétrage d'XL à faire pour que l'ordi s'affranchisse de ces erreurs?
ça y est j'ai trouvé ! Je fait suivre la réponse si je peux aider quelqu'un:
Voilà la réponse que j'ai trouvé dans cette discussion:
https://forum.excel-pratique.com/excel/erreur-de-calcul-t42196.html
eriiic a écrit :Bonjour,
C'est dû aux erreur d'arrondi suite aux conversions décimal/binaire/décimal.
Un nombre 'pile' en décimal ne tombera pas forcement 'pile' en binaire, mais aura une suite infinie de décimales.
33.07-32.92-0.15= -1.41553E-15 et non pas 0 pour excel (et pour de nombreux autres logiciels).
eric
Dans mon exemple précédant la boucle FOR est néfaste: j'ai besoin de contrôler l'arrondie au moment de l'incrémentation et du test de la condition de fin de boucle. Ce n'est pas possible avec FOR-NEXT
Donc ci-dessous le même code qui fonctionne parfaitement peu importe le nombre d'itérations:
La difficulté réside encore dans le choix du nombre de décimales de l'arrondie:
Trop petit => pas assez précis
Trop grand => on retombe dans les même erreurs
L'exemple fonctionne pour 1000 itérations jusqu'à arrondi=12
et aussi pour 65000 itérations (c'est le nb maxi de ligne dans un classeur XL) jusqu'à arrondi=11
(Allez savoir comment ça évolue quand le calcul est plus compliqué que x=x+0.1)
Const Debut As Double = 0
Const Fin As Double = 65000
Const Arrondi As Integer = 11
Dim i As Double, j As Double, text As String
j = 0
i = Round(Debut, Arrondi)
Do
j = j + 1
text = "B" & j
Range(text).Value = i
i = i + 0.1
i = Round(i, Arrondi)
Loop While i <= Fin
