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 :

Probleme de décimales en python


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Octobre 2024
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2024
    Messages : 2
    Par défaut Probleme de décimales en python
    Bonjour,
    J'ai essayé plusieurs solutions pour éditer des résultats avec 2 décimales avec le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def Categorie():
        cursor.execute("SELECT Categorie, SUM(Prix) AS Prix_total FROM liste_achats WHERE Date_achat >='2024-01-01' GROUP BY Categorie")
        rows = cursor.fetchall()
        print('La Dépense totale du 7 Mars 2024 à aujourdhui par catégorie est de :')
        for row in rows:
           print(row)
            #print('%.2f', 2, row)
    #round(value, 3)
    J'obtiens toujours ce type de résultats:

    La Dépense totale du 7 Mars 2024 à aujourd'hui par catégorie est de :
    ('Alcool-Vins', 141.9)
    ('Apéritifs', 93.57000000000002)
    ('Boissons', 166.09999999999997)
    ('Boucherie', 172.51)
    ('Boulangerie', 151.07999999999998)
    ('Bricolage', 4.49)
    ('Café', 103.38999999999999)
    J'aimerai n'avoir que 2 décimales dans mes totaux.
    Merci pour votre aide et votre indulgence

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 062
    Par défaut
    Bonjour,

    row est un tuple, et si vous souhaitez travailler avec les nombres à l'intérieur, vous devrez les extraire de ce tuple.

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par Detoussieu Voir le message
    J'ai essayé plusieurs solutions pour éditer des résultats avec 2 décimales
    Par définition une solution doit fonctionner et si c'était le cas vous ne seriez pas là pour demander de l'aide.
    Et votre premier soucis (on ignorera ceux posés par l'utilisation de floats pour représenter de la monnaie) est du côté du formatage des chaines de caractères.

    Vous avez essayé print('%.2f', 2, row) (que l'on trouve en commentaire dans votre code) qui ne fonctionne pas parce que mal utilisé.
    '%.2f pourrait le faire mais appliqué à un nombre flottant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> '*** %.02f ***' % 0.1
    '*** 0.10 ***'
    et vous voyez que cette construction ressemble à un appel de fonction où on a un patron de chaine de caractères ('*** %.02f ***') où un bout sera remplacé par un argument. Cette représentation est héritée du langage C. Avec python on peut aussi écrire cela comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> '*** {0:.02f} ***'.format(0.1)
    '*** 0.10 ***'
    >>>
    Puisque c'est une sorte d'appel de fonction, s'il y a 2 arguments à passer, il va falloir dire quoi en faire et retrouver les "place-holders" correspondants dans le patron.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> '*** %.02f *** %s xxx' % (0.1, 'aaa')
    '*** 0.10 *** aaa xxx'
    >>> '*** {0:.02f} *** {1:s} xxx'.format(0.1, 'aaa')
    '*** 0.10 *** aaa xxx'
    >>>
    Voilà... à part ça il y a plein de tutos gratuits et des tas d'articles qui couvrent le sujet. à vous de prendre le temps de comprendre ce que vous lisez...

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

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    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 486
    Billets dans le blog
    6
    Par défaut
    Bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print(round(151.07999999999998, 2))
    151.08

  5. #5
    Membre Expert
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 923
    Billets dans le blog
    8
    Par défaut
    Bonjour,
    Pour être*exhaustif j'ajouterai le formatage avec un fstring:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> f'*** {0.1:.02f} ***'
    '*** 0.10 ***'
    >>>

  6. #6
    Responsable Arduino et Systèmes Embarqués


    Avatar de f-leb
    Homme Profil pro
    Enseignant
    Inscrit en
    Janvier 2009
    Messages
    13 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 13 196
    Billets dans le blog
    47
    Par défaut
    Bonsoir à tous,

    Est-ce que ce ne serait pas plus intéressant de faire l'arrondi par le SGBD ?
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Categorie, round(SUM(Prix), 2) AS Prix_total FROM liste_achats WHERE...
    Avec round() en SQL (à voir selon le SGBD utilisé).

  7. #7
    Candidat au Club
    Homme Profil pro
    Webmaster
    Inscrit en
    Octobre 2024
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Webmaster
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2024
    Messages : 2
    Par défaut
    Citation Envoyé par f-leb Voir le message
    Bonsoir à tous,

    Est-ce que ce ne serait pas plus intéressant de faire l'arrondi par le SGBD ?
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Categorie, round(SUM(Prix), 2) AS Prix_total FROM liste_achats WHERE...
    Avec round() en SQL (à voir selon le SGBD utilisé).
    Bonsoir
    Merci d'avoir pris le temps de me proposer une solution apparemment simple et qui fonctionne
    Un passionné débutant

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par f-leb Voir le message
    Est-ce que ce ne serait pas plus intéressant de faire l'arrondi par le SGBD ?
    Faire l'arrondi à n décimales n'est pas la même chose qu'afficher un nombre avec n-decimales.
    Si j'écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    >>> round(123.1, 2)
    123.1
    ce n'est pas pareil qu'afficher 2 chiffres après la virgule:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> '%.02f' % 123.1
    '123.10'
    >>>
    Citation Envoyé par MPython Alaplancha Voir le message
    Bonjour,
    Pour être*exhaustif j'ajouterai le formatage avec un fstring:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    >>> f'*** {0.1:.02f} ***'
    '*** 0.10 ***'
    >>>

    Mouais... essayez f-string avec des tuples, vous comprendrez (peut être!) pourquoi on va pouvoir ignorer cette possibilité

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

  9. #9
    Membre Expert
    Avatar de MPython Alaplancha
    Homme Profil pro
    Paysan à 3 francs six sous
    Inscrit en
    Juin 2018
    Messages
    923
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Paysan à 3 francs six sous
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Juin 2018
    Messages : 923
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par wiztricks Voir le message

    vous comprendrez (peut être!)
    - W
    Je reconnais là bien ta signature.

  10. #10
    Membre averti
    Homme Profil pro
    Occupé
    Inscrit en
    Décembre 2021
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Occupé

    Informations forums :
    Inscription : Décembre 2021
    Messages : 31
    Par défaut
    Tant pis, je prends le risque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    tup: tuple = 'Apéritifs', 93.57000000000002
    print(f'{tup[0]}, {tup[1]:.02f}')
     
    Apéritifs, 93.57

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par MagicJohnson Voir le message
    Tant pis, je prends le risque:
    Il n'y a pas de risque: ça fonctionne. C'est lorsqu'on va s'amuser à comparer le rendu des différents formats qu'on pourra préférer l'un ou l'autre.
    Pour l'instant, vous n'avez fait qu'une toute petite partie du boulot...


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

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par f-leb Voir le message
    Avec round() en SQL (à voir selon le SGBD utilisé).
    Ou cast() qui est standard et donc utilisable par tout SGBD... => select Categorie, cast(SUM(Prix) as decimal(20, 2)) AS Prix_total FROM liste_achats WHERE....
    Mais je plussoie le fait de déporter ce problème au SGBD (plus on décharge Python de taches annexes et faisables par d'autres mieux c'est). D'autant plus qu'il y a une différence entre Python et SGBD
    En Python: round(12.245, 2) donne 12.24 (malgré le fait que le 3° chiffre soit un "5" ce qui, dans les règles standard aurait dû donner 12.25) tandis que le SGBD Postgres, lui, donne bien 12.25.
    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]

  13. #13
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Ou cast() qui est standard et donc utilisable par tout SGBD... => select Categorie, cast(SUM(Prix) as decimal(20, 2)) AS Prix_total FROM liste_achats WHERE....
    Très bonne idée qui ne marche pas! Si sqlite3 (probablement utilisé ici) connait CAST, il ne connait pas decimal (et on ne pourra "caster" que sur des types supportés).

    Quand à round qu'il soit fait côté Python ou côté SGDB, pour afficher des centimes, ça ne le fait pas.

    Citation Envoyé par Sve@r Voir le message
    Mais je plussoie le fait de déporter ce problème au SGBD
    C'est ce qu'on fait en général mais dans le cas particulier, que le round soit fait côté Python ou SGDB ne va pas changer grand chose. Ce serait différent pour le SUM qu'on peut aussi faire côté Python après avoir transféré un tas de tuples, ce qui prend du temps, consomme de la bande passante et n'apporte rien vs le SUM fait coté SGDB.

    edit - en fait sqlite supporte "un peu", le code suivant sort:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import sqlite3
     
    cx=sqlite3.connect(":memory:")
    cx.execute("CREATE TABLE produits(nom TEXT, prix DECIMAL(6, 2))")
    cx.execute("INSERT INTO produits VALUES('Pommes', 10.25), ('Poires', 10.25)")
     
    res = cx.execute("SELECT * FROM produits")
    for row in res.fetchall():
        print(row)
    sort:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ('Pommes', 10.25)
    ('Poires', 10.25)
    et ça à l'air de marcher... mais si on récupère la sortie de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    res = cx.execute("SELECT CAST(SUM(prix) AS DECIMAL(6,2)) FROM produits")
    for row in res.fetchall():
        v, = row
        print("ligne: %s (type=%s)" % (v, type(v)))
    on a ligne: 20.5 (type=<class 'float'>)car le CAST mappe sur NUMERIC qui devient float en Python et toujours pas de centimes!!!

    Note en fait le DECIMAL ne fait pas grand chose: avec d'autres données,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import sqlite3
     
    cx=sqlite3.connect(":memory:")
    cx.execute("CREATE TABLE produits(nom TEXT, prix DECIMAL(6,2))")
    cx.execute("INSERT INTO produits VALUES('Pommes', 10.2534), ('Poires', 10.25)")
     
    res = cx.execute("SELECT * FROM produits")
    for row in res.fetchall():
        print(row)
     
    res = cx.execute("SELECT CAST(SUM(prix) AS DECIMAL(6,2)) FROM produits")
    for row in res.fetchall():
        v, = row
        print("ligne: %s (type=%s)" % (v, type(v)))
    on obtient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ('Pommes', 10.2534)
    ('Poires', 10.25)
    ligne: 20.5034 (type=<class 'float'>)
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  14. #14
    Membre averti
    Homme Profil pro
    Occupé
    Inscrit en
    Décembre 2021
    Messages
    31
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Occupé

    Informations forums :
    Inscription : Décembre 2021
    Messages : 31
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    donne 12.24 (malgré le fait que le 3° chiffre soit un "5" ce qui, dans les règles standard aurait dû donner 12.25)
    Il me semble comprendre dans le post initial que Detoussieu souhaite une réponse avec deux décimales mais pas qu'elle soit nécessairement arrondie.

  15. #15
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par MagicJohnson Voir le message
    Il me semble comprendre dans le post initial que Detoussieu souhaite une réponse avec deux décimales mais pas qu'elle soit nécessairement arrondie.
    Un prix s'exprime en unité monétaire où la virgule sépare(ici) euro et centimes d'euros.
    Le format .02f arrondi et ajoute des 0 si nécessaire pour avoir les 2 décimales (qui feront "centimes").
    Le "round" ne fait que l'arrondi.

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

  16. #16
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par MagicJohnson Voir le message
    Il me semble comprendre dans le post initial que Detoussieu souhaite une réponse avec deux décimales mais pas qu'elle soit nécessairement arrondie.
    Si la 3° (et les autres) décimales disparaissent, le résultat final ne pourra qu'être arrondi. Reste à savoir s'il doit l'être systématiquement au plus bas, systématiquement au plus haut, ou selon les règles mathématiques (appelées aussi "règles du banquier")
    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]

Discussions similaires

  1. Problème de programmation en Python
    Par Victoria007 dans le forum Général Python
    Réponses: 4
    Dernier message: 19/09/2008, 12h12
  2. problème de syntaxe en python
    Par akrogames dans le forum Général Python
    Réponses: 3
    Dernier message: 03/02/2008, 20h33
  3. Probleme d'installation de python sous debian
    Par ToMs dans le forum Debian
    Réponses: 3
    Dernier message: 09/08/2006, 10h57
  4. Problème d'encodage avec Python
    Par tse_tilky_moje_imja dans le forum Général Python
    Réponses: 2
    Dernier message: 22/02/2006, 14h36
  5. Réponses: 4
    Dernier message: 10/02/2006, 13h49

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