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

Calcul scientifique Python Discussion :

Problème de calcul


Sujet :

Calcul scientifique Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 3
    Points : 3
    Points
    3
    Par défaut Problème de calcul
    Je suis en train de me former à Python et aux représentations des nombres en binaire. Dans l'IDLE Python, je tape le calcul 15*0,09 le résultat devrait être 1.35 mais l'affichage est 1.34999999999999 . Quelqu'un peut-il me dire très précisément ce qui s'est passé au niveau du codage et pourquoi on a "une erreur"
    Merci d'avance

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 351
    Points : 36 875
    Points
    36 875
    Par défaut
    Salut,
    Il faudrait reprendre les bases de la représentation des nombres réels en binaire mais Wikipedia le fait très bien: IEEE_754
    Si vous voulez la "précision", Python - comme d'autres langages - propose le module decimal
    - W

  3. #3
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 480
    Points : 9 277
    Points
    9 277
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Cela correspond à la manière dont les nombres réels sont stockés. Ils sont représentés en mémoire par un nombre fini de bits, et donc, il y a certains nombres qu'il n'est pas possible de représenter exactement.

    Ce n'est pas spécifique à Python, qui d'ailleurs utilise la bibliothèque du C.

    Pour "échapper" à cela, on peut stocker ces nombres autrement, comme le module decimal de Python le fait. Mais ça consomme plus de mémoire et les calculs sont moins rapides.

    [grillé]

  4. #4
    Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci pour la réponse. J'ai lu la notice du module décimal, mais comment trouver la bonne valeur (1.35) lorsqu'on fait le calcul que j'avais mentionné ? Pour la norme IEEE 754 j'ai compris comment on représente un nombre à virgule en binaire mais cela ne m'explique pas pourquoi 17*0.09 donne "normalement" 1.53 et pourquoi 15*0.09 donne 1.34999999999999999 au lieu de 1.35 et la fonction Decimal(15*0.09) ne donne pas non plus la "bonne" réponse.
    Merci de votre aide.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 351
    Points : 36 875
    Points
    36 875
    Par défaut
    Salut,

    Lire est une chose.
    "Comprendre" signifie savoir faire avec.
    Ce qui en programmation demande de jouer un peu avec pour savoir ce qu'on en a compris.
    Dire: "la précision du résultat dépend de la précision du context du module" restera probablement du volapük tant qu'on ne regarde pas ce que ca donne avec l'interpreteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    >>> from decimal import *
    >>> getcontext().prec=2
    >>> print(Decimal(17)*Decimal(0.09))
    1.5
    >>> getcontext().prec=5
    >>> print(Decimal(17)*Decimal(0.09))
    1.5300
    >>> getcontext().prec=10
    >>> print(Decimal(17)*Decimal(0.09))
    1.530000000
    >>> getcontext().prec=20
    >>> print(Decimal(17)*Decimal(0.09))
    1.5299999999999999434
    >>>
    Pas mal hein...
    Je vous laisse jouer avec les autres paramètres:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> getcontext()
    Context(prec=20, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, 
    clamp=0, flags=[Inexact, FloatOperation, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow])
    - W

  6. #6
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 480
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 480
    Points : 9 277
    Points
    9 277
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Citation Envoyé par pierre6901 Voir le message
    Pour la norme IEEE 754 j'ai compris comment on représente un nombre à virgule en binaire mais cela ne m'explique pas pourquoi 17*0.09 donne "normalement" 1.53 et pourquoi 15*0.09 donne 1.34999999999999999 au lieu de 1.35...
    Comme j'ai dit plus haut:

    Cela correspond à la manière dont les nombres réels sont stockés. Ils sont représentés en mémoire par un nombre fini de bits, et donc, il y a certains nombres qu'il n'est pas possible de représenter exactement.
    La documentation Python donne pas mal d'explications sur le sujet: http://docs.python.org/2/tutorial/floatingpoint.html.

    Les calculs d'encodage/décodage des nombres sous la forme IEEE-754 sont assez compliqués, mais le site http://babbage.cs.qc.edu/IEEE-754/ fait assez bien le boulot! Cependant, si le calcul détaillé t'intéresse, je peux te refaire le calcul! J'ai déjà fait ça dans le passé en assembleur pour "brancher" un fortran sur un processeur arithmétique rapide parce que les 2 formats des flottants étaient différents.

    Les nombres 17 et 15 sont représentés exactement dans le format IEEE-754

    Format des float Python (="double" du C):
    64 bits: 1 bit pour le signe, 11 bits pour l'exposant et 52 bits pour la mantisse

    n = 17
    exposant de 2 = "10000000011"
    mantisse = "0001000000000000000000000000000000000000000000000000"
    recalcul de n = "'17.0000'"

    n = 15
    exposant de 2 = "10000000010"
    mantisse = "1110000000000000000000000000000000000000000000000000"
    recalcul de n = "15.000"

    Mais ce n'est pas le cas de 0.09:

    n = 0.09
    exposant de 2 = "'01111111011',
    mantisse = "0111000010100011110101110000101000111101011100001010"
    recalcul de n = "'0.0899999999999999966693309261245303787291049957275390625'"

    Il y a ensuite une multiplication entre les nombres en format binaires (http://www.altdevblogaday.com/2011/1...-and-addition/), puis le résultat, qui lui aussi est imparfait, est interprété par Python (je n'en connais pas les critères) pour prise en compte et affichage. D'où les différences entre 17*0.09 et 15*0.09.

    Il reste qu'on peut se "débarrasser" du problème en faisant un arrondi judicieux en fonction du contexte du calcul. Par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print round(15*0.09, 15)
    1.35
    Et, comme dit, si on a besoin d'avoir plus de chiffres significatifs, le module decimal le permet (1000 chiffres si on veut!). Voilà par exemple le nombre e calculé avec 1000 décimales:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    e = Decimal("\
    2.718281828459045235360287471352662497757247093699\
    95957496696762772407663035354759457138217852516642\
    74274663919320030599218174135966290435729003342952\
    60595630738132328627943490763233829880753195251019\
    01157383418793070215408914993488416750924476146066\
    80822648001684774118537423454424371075390777449920\
    69551702761838606261331384583000752044933826560297\
    60673711320070932870912744374704723069697720931014\
    16928368190255151086574637721112523897844250569536\
    96770785449969967946864454905987931636889230098793\
    12773617821542499922957635148220826989519366803318\
    25288693984964651058209392398294887933203625094431\
    17301238197068416140397019837679320683282376464804\
    29531180232878250981945581530175671736133206981125\
    09961818815930416903515988885193458072738667385894\
    22879228499892086805825749279610484198444363463244\
    96848756023362482704197862320900216099023530436994\
    18491463140934317381436405462531520961836908887070\
    16768396424378140592714563549061303107208510383750\
    51011574770417189861068739696552126715468895703503\
    63")
    Mais il y aura toujours des erreurs qui dépasseront, quelque soit le nombre de chiffres significatifs: 10/3 par exemple, et il est donc important de savoir décider à quel endroit on "coupe" et quel type d'arrondi on utilise, en fonction du contexte et de l'objectif qu'on a.

    Ok?

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 351
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 351
    Points : 36 875
    Points
    36 875
    Par défaut
    @tyrtamos.
    Decimal fonctionne parce qu'il n'utilise pas la représentation des "float" avec un format fixe comme IEE754.
    - W

  8. #8
    Candidat au Club
    Homme Profil pro
    Enseignant
    Inscrit en
    Novembre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2013
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci à tous

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

Discussions similaires

  1. Problème de calcule en SQL !
    Par FilipeVV dans le forum Langage SQL
    Réponses: 3
    Dernier message: 02/09/2005, 11h45
  2. Problème de calcul matricielle
    Par Clad3 dans le forum Algorithmes et structures de données
    Réponses: 21
    Dernier message: 29/06/2005, 21h45
  3. problème de calcul des normales par sommet
    Par captainSeb dans le forum OpenGL
    Réponses: 2
    Dernier message: 21/01/2005, 13h42
  4. [Calendar]Problème de calcul de date
    Par valerie90 dans le forum Collection et Stream
    Réponses: 6
    Dernier message: 08/12/2004, 12h13
  5. Problème de calcul unix_timestamp
    Par petit_stagiaire dans le forum Administration
    Réponses: 2
    Dernier message: 28/04/2004, 15h27

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