IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

[Débutant] Imprécision des nombres à virgule flottante


Sujet :

Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut [Débutant] Imprécision des nombres à virgule flottante
    Bonjour,

    J'écris un petit programme en pyOpengGL pour apprendre l'OpenGL et le python.
    Après de nombreuses galères, j'ai identifié ce qui me bloque et je l'ai résumé ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    monnombre = -1.0
    while monnombre < 0.1:
      monnombre+=0.1
      print monnombre
    input()
    Ce petit bout de code renvoit :
    -0.9
    -0.8
    -0.7
    -0.6
    -0.5
    -0.4
    -0.3
    -0.2
    -0.1
    -1.381354646 e-16
    0.1
    0.2
    Question : pourquoi est ce que l'on ne passe pas de -0.1 à 0.0 ?

    Merci d'avance

  2. #2
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Parce que les nombres flottants sont intrinsèquement imprécis*! C’est en général négligeable (10^-16 est, normalement, une approximation acceptable de 0.0), mais cela peut effectivement parfois poser problème –*il n’y a pas grand chose d’autre à faire dans ce cas que d’en tenir compte au moment de la programmation…

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    merci pour ta réponse mont29.
    Je suis un peu blasé d'avoir perdu autant de temps pour un truc aussi idiot :s mais au moins je sais ce qu'il en est !

    Je n'avais jamais rencontré cela, est-ce spécifique à python ?
    Quelqu'un connait-il le pourquoi de cet "imprécision intrinsèque" ?

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Comme l'a dit mont29, les flottants (mêmes décimaux donc pour nous "finis") sont imprécis à cause de la façon dont un ordi code un flottant en binaire. Le codage consiste à multiplier par 2 et à garder la partie entière et à s'arrêter quand le décimal arrive à 0. Mais parfois ça n'arrive pas
    Prend par exemple 0.6.
    0.6 * 2 = 1.2 => on garde 1 et il reste 0.2
    0.2 * 2 = 0.4 => on garde 0 et il reste 0.4
    0.4 * 2 = 0.8 => on garde 0 et il reste 0.8
    0.8 * 2 = 1.6 => on garde 1 et il reste 0.6
    0.6 * 2 = 1.2 ...
    Donc 0.6 se code en binaire 1001 1001 1001 1001 ...... etc etc etc à l'infini. Et au décodage binaire => décimal ben tu retrouves pas tout à fait 0.6. Et donc si tu tapes 0.6 dans une console Python, le système te renvoie 0.59999999 (et ce n'est pas spécifique à Python mais au processeur donc ça arrivera dans tous les langages bas niveaux comme C ou C++ ou Pascal)

    Généralement on fait avec parce que généralement l'imprécision aussi minime ne gêne pas. Mais si ça gêne vraiment (comme par exemple dans un calcul bancaire), alors faut utiliser des outils dédiés comme par exemple la librairie decimal. Cette librairie est plus longue que le calcul natif car elle décortique et calcule un flottant chiffre par chiffre (comme au primaire) mais elle garantit en retour des calculs rigoureusement exacts

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import decimal
    a=decimal.Decimal("0.6")
    print a, a*a, a*a*a   => 0.6 0.36 0.216

    Code Python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import decimal
    monnombre = decimal.Decimal("-1.0")
    while monnombre < decimal.Decimal("0.1"):
      monnombre+=decimal.decimal("0.1")
      print monnombre
    input()

    Citation Envoyé par mont29 Voir le message
    il n’y a pas grand chose d’autre à faire dans ce cas que d’en tenir compte au moment de la programmation…
    Ben justement non !!!
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut
    Merci pour les précision Sve@r !

    Ce n'est pas que j'ai besoin d'une grande précision, car je n'utilise que des chiffres avec 1 ou 2 nombres après la virgules, mais je les compares à 0 !

    donc, si mon calcule du genre 0.1 -= 0.1 ne me renvoi pas 0, ma fonction n'entre pas dans le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    if (mvt_gauche==1) :
        if (dirz >= 0 and dirx > 0) :
          dirx -= 0.1
          dirz += 0.1
        elif (dirz > 0 and dirx < 0) :
          dirx -= 0.1
          dirz -= 0.1
        elif (dirz <= 0 and dirx < 0) :
          dirx += 0.1
          dirz -= 0.1
        elif (dirz < 0 and dirx >= 0) :
          dirx += 0.1
          dirz += 0.1

  6. #6
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 986
    Points
    30 986
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Saturnin123 Voir le message
    Ce n'est pas que j'ai besoin d'une grande précision, car je n'utilise que des chiffres avec 1 ou 2 nombres après la virgules
    La précision ne dépend pas forcément du nombre de chiffres après la virgule. Dans mon exemple, 0.6 n'a qu'un chiffre après la virgule mais malgré ça, tu n'arriveras pas à récupérer 0.6 en utilisant le calcul natif flottant. Et imagine ton compte bancaire perdre qq centimes à chaque opération, j'aimerais voir ta tronche si ton banquier te répond "pas besoin de précision vu qu'il n'y a que 2 décimales"...

    Citation Envoyé par Saturnin123 Voir le message
    , mais je les compares à 0 !


    donc, si mon calcule du genre 0.1 -= 0.1 ne me renvoi pas 0, ma fonction n'entre pas dans le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    if (mvt_gauche==1) :
        if (dirz >= 0 and dirx > 0) :
          dirx -= 0.1
          dirz += 0.1
        elif (dirz > 0 and dirx < 0) :
          dirx -= 0.1
          dirz -= 0.1
        elif (dirz <= 0 and dirx < 0) :
          dirx += 0.1
          dirz -= 0.1
        elif (dirz < 0 and dirx >= 0) :
          dirx += 0.1
          dirz += 0.1
    Ben en programmation, on prend vite l'habitude de ne jamais faire d'égalités strictes entre les flottants parce que justement on n'est pas certain d'avoir l'égalité. Si on doit comparer par exemple un nombre x avec un nombre y, on remplacera if x == y par if abs(x-y) < 1e-10...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 24
    Points : 10
    Points
    10
    Par défaut

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 9
    Dernier message: 22/05/2021, 15h33
  2. Réponses: 64
    Dernier message: 14/02/2011, 14h02
  3. stockage des nombres à virgule flottante
    Par Alexdezark dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 24/11/2008, 10h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo