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 sub

Au 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 Sub

Pour 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 double

On 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

Pour moi pas de souci

Voilà ce que j'obtiens au 10ème clic

precision
Banzai64 a écrit :

Bonjour

Pour moi pas de souci

Voilà ce que moi j'obtiens au 10e clic:

precision

Une erreur à la 16e décimal dont je me ficherais bien si elle ne faisait pas bugger mon programme!

C'est désespérant!

et j'observe la même chose sur les 2 machines où j'ai pu tester jusqu'à maintenant

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 Sub

Tu 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 i

Voilà 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.

precision2

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
Rechercher des sujets similaires à "erreur presions calcul trop elevee"