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 :

Fonction et nombre flottant déconseillé


Sujet :

Python

  1. #1
    Membre averti
    Inscrit en
    mars 2004
    Messages
    1 828
    Détails du profil
    Informations forums :
    Inscription : mars 2004
    Messages : 1 828
    Points : 405
    Points
    405
    Par défaut Fonction et nombre flottant déconseillé
    Bonjour,

    j'ai la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def f(x,y,z):
      if x+y == z:
        return True
      else:
        return False
    Apparemment, il est déconseillé d'utiliser des nombres flottants, mais je ne comprends a pourquoi car
    les entiers sont autorisés, les chaînes de caractères aussi et aussi les listes.

    merci d'avance pour votre aide.

  2. #2
    Membre chevronné

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    mars 2013
    Messages
    1 171
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : mars 2013
    Messages : 1 171
    Points : 2 213
    Points
    2 213
    Par défaut
    Dans votre terminal, tapez

    Vous observerez que le résultat est False. Voilà pourquoi votre fonction, écrite comme elle est, n'est pas recommandée pour les flottants. C'est un exemple avec 3 termes, mais il en existe aussi avec 2 termes c'est certain, je n'en ai juste pas sous la main.

    Donc ceci répond à votre question "pourquoi n'est ce pas conseillé pour les flottants". Maintenant ça vous amène forcément à une nouvelle question : pourquoi 0.1+0.1+0.1 n'est pas égal à 0.3 ? Ceci est dû à la représentation mémoire en binaire des nombres flottants. En tapant ces mots clés, vous allez trouvez plein de choses (il y en a sur ce site), dont des explications détaillées du célèbre exemple que je vous ai fourni.

  3. #3
    Membre averti
    Inscrit en
    mars 2004
    Messages
    1 828
    Détails du profil
    Informations forums :
    Inscription : mars 2004
    Messages : 1 828
    Points : 405
    Points
    405
    Par défaut
    Merci!
    Du coup comment faudrait-il écrir la fonction pour que ce soit toujours vrai avec des nombres flottants ?

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    décembre 2007
    Messages
    4 201
    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 201
    Points : 8 731
    Points
    8 731
    Billets dans le blog
    6
    Par défaut
    Bonjour

    L'erreur relative commise à cause du stockage des nombres flottants en mémoire est très faible, en général inférieure à 10e-15, c'est à dire 0.00000000000001.

    Selon le programme, on peut donc se fixer une limite de précision acceptable.
    Par exemple, remplacer la condition A==B par:

    Exemple pour reprendre le cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print(0.1+0.1+0.1==0.3)
    False
    On peut faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print(abs((0.3-(0.1+0.1+0.1))/0.3)<10e-15)
    True
    Ceci dans le cas général, mais selon les nombres en question, on peut simplifier. Par exemple, si on est sûr que A est toujours supérieur à B, on peut se passer de abs(...). Toujours selon les cas, on peut comparer directement A-B à 10e-15. Etc...
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Membre averti
    Inscrit en
    mars 2004
    Messages
    1 828
    Détails du profil
    Informations forums :
    Inscription : mars 2004
    Messages : 1 828
    Points : 405
    Points
    405
    Par défaut
    Merci!

  6. #6
    Membre averti
    Profil pro
    Administrateur
    Inscrit en
    mai 2008
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Administrateur
    Secteur : Industrie

    Informations forums :
    Inscription : mai 2008
    Messages : 237
    Points : 433
    Points
    433
    Par défaut
    Python stocke les nombres en virgule flottante sous forme de fraction en base 2
    0.125 devient 1/10 + 2/100 + 5/1000
    Ainsi la précision de pi est différente d'un sytème à un autre;

    Avec les nombres en virgule flottante, on doit tenir compte de leur précision.
    Cela n'a aucun sens de dire qu'ils sont déconseillés ou pas.
    Tout est question de l'usage qu'on en fait
    En général, on va les utiliser pour faire un calcul numérique qui demande une certaine précision.

    Calculez
    • La distance entre x+y et z
    • Ou la valeur absolue de la différence
    • Puis testez si elle est proche de 0


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    def f(x,y,z):
      e = 0.0000001;
      if math.sqrt( (x+y-z)**2 ) < e:
        return True
      else:
        return False

  7. #7
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    janvier 2009
    Messages
    791
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : janvier 2009
    Messages : 791
    Points : 1 476
    Points
    1 476
    Par défaut
    Bonjour

    pour bien enfoncer le clou ... et "dédouaner" python.

    Ce n'est pas inhérent à python mais à la représentation des réels en machine (selon la norme IEEE 754).

    Le même "problème" en C en traduisant la fonction f présentée dans les posts précédents de deux façons :

    Code C : 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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    #define EPSILON 1e-15
     
    int f_strict(double x, double y, double z)
    {
        if ((x + y) == z)
            return 1;
        else
            return 0;
    }
     
    int f_epsilon(double x, double y, double z)
    {
        if (fabs((x + y) - z) < EPSILON)    
            return 1;
        else
            return 0;
    }
     
     
    int main(int argc, char *argv[])
    {
        double x = atof(argv[1]);   
        double y = atof(argv[2]);   
        double z = atof(argv[3]);   
     
     
        fprintf(stdout, "fonction f_strict : %d\n", f_strict(x, y, z));
        fprintf(stdout, "fonction f_epsilon: %d\n", f_epsilon(x, y, z));
    }

    à l'exécution (0 pour False, 1 pour True):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    prompt> flottant.exe .1 .2 .3
    fonction f_strict : 0
    fonction f_epsilon: 1
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

  8. #8
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    février 2009
    Messages
    6 387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : février 2009
    Messages : 6 387
    Points : 23 533
    Points
    23 533
    Billets dans le blog
    124
    Par défaut
    Citation Envoyé par plxpy Voir le message
    Bonjour

    pour bien enfoncer le clou ... et "dédouaner" python.

    Ce n'est pas inhérent à python mais à la représentation des réels en machine (selon la norme IEEE 754).
    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    # En Julia, on n'utile pas un égal mais un &#8776; créé par \approx + TAB
     
    @show 0.1 + 0.1 + 0.1 &#8776; 0.3 # 0.1 + 0.1 + 0.1 &#8776; 0.3 = true

    Le codage Julia du site DVP le traite mal, en PRE :

    @show 0.1 + 0.1 + 0.1 ≈ 0.3 # 0.1 + 0.1 + 0.1 ≈ 0.3 = true

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    juin 2008
    Messages
    18 681
    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 : 18 681
    Points : 32 253
    Points
    32 253
    Par défaut
    Citation Envoyé par danielhagnoul Voir le message
    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    # En Julia, on n'utile pas un égal mais un &#8776; créé par \approx + TAB
     
    @show 0.1 + 0.1 + 0.1 &#8776; 0.3 # 0.1 + 0.1 + 0.1 &#8776; 0.3 = true

    Le codage Julia du site DVP le traite mal, en PRE :

    @show 0.1 + 0.1 + 0.1 ≈ 0.3 # 0.1 + 0.1 + 0.1 ≈ 0.3 = true
    Ça veut juste dire que Julia introduit une fonction "almost equal" qui peut s'écrire ≈.
    La fonction Python équivalente est math.isclose mais il n'y a pas d'équivalent syntaxique à ≈.

    Mais çà ne change rien au problème de départ, si on écrit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    def f(x,y,z):
      if x+y == z:
        return True
      else:
        return False
    on ne sait pas plus tester l'égalité pour des nombres flottants....
    Si on veut que cette fonction s'applique aussi à ces nombres là, il va falloir tester le type des arguments et appliquer l'opérateur qui va bien.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. Réponses: 8
    Dernier message: 08/06/2006, 18h05
  2. Réponses: 9
    Dernier message: 30/03/2006, 17h44
  3. Réponses: 4
    Dernier message: 31/10/2005, 18h48
  4. nombres flottants arrondis aux 5 centimes
    Par nstubi dans le forum Langage
    Réponses: 3
    Dernier message: 17/09/2004, 10h02
  5. [Kylix] Probleme de nombre flottant!!
    Par yopziggy dans le forum EDI
    Réponses: 5
    Dernier message: 02/05/2002, 11h13

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