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

MySQL Discussion :

Données avec décimales : DECIMAL ou FLOAT ?


Sujet :

MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Par défaut Données avec décimales : DECIMAL ou FLOAT ?
    Bonjour à tous,

    Je viens vers vous pour un problème de chiffres avec décimales.

    Habituellement je met ma colonne en FLOAT, mais étrangement un chiffre tel que 95.47 se transforme en 95.50, ce qui est assez compliquer puisque c'est pour un module de comptabilité.

    Donc ma question est : Est-ce normal cet arrondi à l'entier (0.47 -> 0.50)
    Est-ce que si je configure mon champ en DECIMAL plutôt que FLOAT règlerai le problème ?
    Si oui quel est exactement la différence entre FLOAT et DECIMAL puisque il sont sensé tout les deux enregistré des nombres avec décimales.

    D'avance merci
    Bien à vous
    Spliffer

  2. #2
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Billets dans le blog
    12
    Par défaut
    Salut,

    tout est expliqué dans la doc MySQL par ici
    Quand tu codes de la compta, tu dois garder une représentation exacte et non arrondie de tes valeurs numériques, donc exit le format FLOAT et bonjour le format DECIMAL.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par rawsrc Voir le message
    donc exit le format FLOAT et bonjour le format DECIMAL.
    Ah bon ?
    J'avais cru le contraire...
    Il va falloir que je revois certains de mes scripts.....

  4. #4
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Novembre 2007
    Messages
    274
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 274
    Par défaut
    Bonjour,

    Actuellement la colonne est mit en FLOAT, et depuis phpmyadmin je modifie une ligne qui contient 47.50, j’introduis à la place 47.47 et une fois l'enregistrement effectué il m'affiche 47.50...

    Merci pour le lien où tout est dit, sauf que je comprend pas l'anglais et que la traduction google translate est vraiment pas top, d'où le fait que je demande une explication sur les différence entre FLOAT et DECIMAL en français :p

  5. #5
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    MySQL supports all standard SQL numeric data types. These types include the exact numeric data types (INTEGER, SMALLINT, DECIMAL, and NUMERIC), as well as the approximate numeric data types (FLOAT, REAL, and DOUBLE PRECISION).
    De ce que je comprends de la phrase, DECIMAL est une valeur exacte alors que FLOAT est une valeur approchée.
    Le problème étant que lorsque tu définis un champ DECIMAL en base, il faut que tu indiques le nombre de décimales et que ça a l'air de faire des arrondis si tu dépasses le nombre de décimales autorisées

    Pour tester, je viens d'insérer 10 dans un champ DECIMAL (à 3 chiffres après la virgule) et dans un champ FLOAT. J'ai ensuite passé deux requêtes SQL : une qui divise les deux champs par 3 et une qui re-multiplie les deux champs par 3.
    Au final, j'obtiens 9.999 pour le champ DECIMAL et 10 pour le champ FLOAT.

    Donc, empiriquement, j'aurais tendance à dire que FLOAT est plus précis.

    Amis de la rubrique SGDB, un avis sur la question ?

    A noter que tout ça, c'est sans prendre compte le problème dans PHP...
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  6. #6
    Invité
    Invité(e)
    Par défaut
    Bonjour Celira,
    j'ai tendance à penser comme toi... et je pense savoir pourquoi.

    La confusion vient des expressions et COMPREHENSION de :
    • "valeur exacte" (Exact Value)
    • et "valeur approximative" (Approximate Value)


    "valeur EXACTE" NE VEUT PAS DIRE "valeur JUSTE" !

    En reprenant ton exemple :
    • en DECIMAL ("valeur exacte"), (10 / 3) affiche 3.333 exactement : la valeur a été ARRONDIE DEFINITIVEMENT à la 3ème décimale, sans plus rien derrière (la VALEUR est "EXACTE", mais le calcul n'est pas JUSTE !)
    • en FLOAT ("valeur approximative"), (10 / 3) affiche 3.333 MAIS vaut en réalité 3.3333333.... : donc 3.333 est "approximatif" !

    Lorsqu'on re-multiplie par 3 :
    • en "valeur exacte", ((10 / 3) * 3) affiche 9.999 (exactement)
    • en "valeur approximative", ((10 / 3) * 3) affiche 10 (MAIS vaut en réalité 9.999999.... ARRONDI à 10, donc "approximatif") !


    Sauf erreur de ma part,
    • il est plus correct de traiter/calculer les données en FLOAT qu'en décimal...
    • MAIS ATTENTION aux COMPARAISONS : en "valeur approximative", l'affichage "3.333" peut valoir en réalité 3.3331 ou 3.3330612 -> PAS POSSIBLE d'établir alors une EGALITE STRICTE.


    On peut reproduire le phénomène en PHP :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    $number = 10;
     
    $float = ($number/3); // float (par défaut)
    echo $float.'<br/>';
    echo ($float*3) .'<br/>';
     
    echo '<br/>';
     
    $decimal = (number_format( ($number/3), 3 ) ); // nombre à 3 décimales (arrondi : valeur EXACTE mais PAS JUSTE)
    echo $decimal.'<br/>';
    echo ($decimal*3) .'<br/>';
    ?>
    on obtient :
    3.3333333333333
    10

    3.333
    9.999
    CONCLUSION :

    • l'EXACTITUDE d'un nombre n'a rien à voir avec la JUSTESSE (du calcul).


    CQFD !
    Ce Qu'un Fou Dirait
    Dernière modification par Invité ; 19/09/2017 à 15h49.

  7. #7
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 998
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 998
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Celira Voir le message
    Pour tester, je viens d'insérer 10 dans un champ DECIMAL (à 3 chiffres après la virgule) et dans un champ FLOAT. J'ai ensuite passé deux requêtes SQL : une qui divise les deux champs par 3 et une qui re-multiplie les deux champs par 3.
    Au final, j'obtiens 9.999 pour le champ DECIMAL et 10 pour le champ FLOAT.
    Lorsque vous divisez par 3 un décimal doté d'une précision de 3 décimales après la virgule il respecte à la lettre les décimales indiquées. Or 10 / 3 = 3.333. Donc 3 * 3.333 = 9.999. Le résultat est parfaitement correct et totalement exact eut égard au respects des types de données.
    En revanche, l'utilisation du FLOAT dont les nombres sont encodés en puissance de 2, donne des résultats approximatifs dès que l'on calcule avec des décimales et ceci parce qu'un chiffre à virgule exact en puissance de 10 peut s'avérer a virgule infinie en base 2. Un exemple est 0,2 qui en base deux s'écrit :
    0.001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001001...

    Malheureusement, la machine ayant 32 ou 64 bits commet une approximation et arrête son calcul à :
    0.001001001001001001001001001001001001001001001001001001001001001 (64 bits)
    Cette toute petite erreur, lorsqu'elle est cumulée donne des résultats faux et les comptables passent des nuits blanches a essayer en vain de récupérer les erreurs imbéciles que les informaticiens ignares ont fait trainer en modélisant mal leurs bases de données !

    Donc, empiriquement, j'aurais tendance à dire que FLOAT est plus précis.

    Amis de la rubrique SGDB, un avis sur la question ?

    A noter que tout ça, c'est sans prendre compte le problème dans PHP...
    A +

    PS : aujourd’hui les autorités financières exigent des logiciels certifiés capable de travailler avec au moins 12 décimales après la virgule. Compte tenu de certaines monnaies (dollar zimbabwéen par exemple...) il faut donc mettre du DECIMAL(50,12).
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par rawsrc Voir le message
    Quand tu codes de la compta, tu dois garder une représentation exacte et non arrondie de tes valeurs numériques, donc exit le format FLOAT et bonjour le format DECIMAL.
    C'est pour ça que pour les impôts, on nous demande la somme ARRONDIE à l'ENTIER le plus proche, mais pas à la 2ème décimale...

    Quant au TTC, TVA, HT, il faut utiliser une des formules :
    • (TVA) = (HT) * (tva%)
    • (TTC) = (HT) + (TVA)

    ou (en partant du TTC) :
    • (TVA) = (TTC) * (1-tva%/100)
    • (HT) = (TTC) - (TVA)

    En clair : on ne calcule pas séparément la TVA et le HT, en espérant que la somme fasse le TTC...

  9. #9
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Est-ce que le problème se produit uniquement avec une insertion depuis PHP ou également si tu essayes de faire la modification en direct sur la base (par PhpMyAdmin par exemple) ?

    Si c'est uniquement en PHP, pourrais-tu nous montrer le code qui fait l'enregistrement ?
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  10. #10
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 883
    Par défaut
    Salut splifferwolf.

    Citation Envoyé par splifferwolf
    Donc ma question est : Est-ce normal cet arrondi à l'entier (0.47 -> 0.50)
    Déjà, il ne faut pas confondre la représentation en mémoire des nombres et les arrondis. Ce sont deux choses différentes !

    Citation Envoyé par splifferwolf
    Est-ce que si je configure mon champ en DECIMAL plutôt que FLOAT règlerai le problème ?
    La réponse a été donnée par rawsrc :

    Citation Envoyé par rawsrc
    Quand tu codes de la compta, tu dois garder une représentation exacte et non arrondie de tes valeurs numériques, donc exit le format FLOAT et bonjour le format DECIMAL.
    Juste une petite précision, ce n'est pas une représentation arrondie mais une représentation approximative.

    La différence est dans la représentation du nombre qui est stockée en mémoire.
    Dans le cas du décimal sous mysql, la représentation est codé DCB pour décimal codé binaire (ou packed).
    Un nombre code 3.14159 sera stockée selon le format que vous lui indiqué, par exemple ici, 5 chiffres après la virgule et au total 7 chiffres.
    Comment cela se code en mémoire ? On remplace chaque chiffre par sa représentation hexadécimale.
    Je rappelle qu'un hexadécimal, c'est du binaire qui est codifié que sur quatre bits, soit un valeur allant de 0 à 15.

    1 --> 0001
    2 --> 0010
    3 --> 0011
    ...
    7 --> 0111
    8 --> 1000
    9 --> 1001

    Chaque chiffre utilise donc pour sa représentation quatre bits.
    Votre nombre comprenant 6 chiffres aura une occupation mémoire de 6x4 bits soit 24 bits + le signe.

    En ce qui concerne le flottant, la représentation mémoire est approximative car on cherche à représenter ce nombre sous la forme de puissance de 2.
    Et vos puissances peuvent être négative. Ainsi votre nombre 0.5 a comme représentation 2^-1 soit 1/2. Votre exemple tombe juste
    Mais si nous prenons 0.47, la représentation de ce nombre est infinie si on l'exprime sous forme de puissance de 2.
    Où 0.47 = somme des 2 puissance i allant de + l'infinie à - l'infinie telle que cette somme soit inférieure ou égale à votre nombre, ce qui donne :
    --> 1/4 + 1/8 + 1/16 + 1/1024 + ...
    --> 0.4697265625

    Et comme le stockage en mémoire est limitée à un certain nombre de bits, le nombre que vous obtenez est approximatif.
    Pour l'exemple admettons que le stockage se fasse sur quatre chiffres après la virgule, ce qui donne : 0.4697.
    Et qu'à l'affichage cela se fasse sur trois chiffres après la virgule.
    L'arrondi au plus près, va se faire sur ce quatrième décimal et donne donc : 0.4697 + 0.0005 soit 0.4702
    Et à l'affichage, vous aurez 0.470 soit 0.47.

    Remarque : il y a toujours un arrondi qui se fait sur la représentation flottante.
    A l'inverse aucun arrondi ne se fait sur la représentation décimale.

    En résumé, quand vous faites un calcul genre comptable ou la précision est de rigueur, vous devez utiliser le type décimal.
    Par contre, dans la notation scientifique où le résultat est approximatif, vous devez utiliser float ou double.

    P.S.: avant le passage à l'euro, nous utilisions des devises comme la lire italienne.
    En gros système, dans la représentation decimal (packed), nous stockions des nombres allant jusqu'à 8 octets, soit 16 héxadecimals.
    Je rappelle que cela comprend la partie décimal (2 digits) et la partie entière (13 digits) et le signe (1 digit), soit un total de 16 chiffres digits (ou hexadécimal).
    Or il se trouve que nous rencontrions des problèmes de stockage car nous étions confrontés à des montants gigantesques où le nombre pouvaient s'exprimer en millions de milliard de lire italienne, soit 15 chiffres en partie entières or nous en disposions que de 13.
    Dans ce cas là, nous devions stocker le nombre en partie entière.

    @+

  11. #11
    Membre éclairé

    Homme Profil pro
    Retraite
    Inscrit en
    Octobre 2005
    Messages
    510
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Aude (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Retraite
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 510
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    Salut splifferwolf.


    P.S.: avant le passage à l'euro, nous utilisions des devises comme la lire italienne.
    En gros système, dans la représentation decimal (packed), nous stockions des nombres allant jusqu'à 8 octets, soit 16 héxadecimals.
    Je rappelle que cela comprend la partie décimal (2 digits) et la partie entière (13 digits) et le signe (1 digit), soit un total de 16 chiffres digits (ou hexadécimal).
    Or il se trouve que nous rencontrions des problèmes de stockage car nous étions confrontés à des montants gigantesques où le nombre pouvaient s'exprimer en millions de milliard de lire italienne, soit 15 chiffres en partie entières or nous en disposions que de 13.
    Dans ce cas là, nous devions stocker le nombre en partie entière.

    @+
    ce n'est pas une critique

    c'est pour cela par exemple qu'IBM a proposé sur 128 bit et un codage sur plus de 256 chiffres(et plus beaucoup plus) pour limité les dérives sur des nombres pas quantifiables mais significatif avec une autre définition que float ou double, dcml par défaut 31 chiffres (pour l'AS400) mais j'ai exploré sur PC et même as400 en c++ on peut aller beaucoup plus loin mais sur d’énorme calcul de masse après cela a un impacte sur le temps .
    un prof de math Prof. Richard Kaiser avec son site http://www.rkaiser.de/ c'est servit de la mise a dispos gratuitement de cette lib pour expliquer les math...

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

Discussions similaires

  1. [phpMyAdmin] importation de données avec décimales
    Par tapi21 dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 3
    Dernier message: 29/08/2011, 15h41
  2. [C#] Convertir decimal en float avec SQLDataReader
    Par lancer83 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 26/07/2006, 09h29
  3. Modifier le nom d'une base de donnée avec erreur sy
    Par mmn dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 25/11/2003, 10h12
  4. PB : affichage de données avec accent sous delphi 6
    Par kinda dans le forum Débuter
    Réponses: 3
    Dernier message: 03/07/2003, 13h19
  5. Réponses: 13
    Dernier message: 20/03/2003, 08h11

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