Quand utiliser float vs decimal


14

Je crée cette API, et la base de données stockera des valeurs qui représentent l'un des éléments suivants:

  • pourcentage
  • moyenne
  • taux

Honnêtement, je n'ai aucune idée de la façon de représenter quelque chose dont la plage est comprise entre 0 et 100% en nombre. Devrait-ce être

  • 0,00 - 1,00
  • 0,00 - 100,00
  • toute autre alternative que je ne connais pas

Y a-t-il un choix clair pour cela? Une manière globale de représenter dans les bases de données quelque chose qui va de 0 à 100%? Pour aller plus loin, quel est le type correct pour lui, flottant ou décimal?

Je vous remercie.



5
Les numéros peuvent être stockés de plusieurs façons. Il n'y a rien de fondamentalement mauvais à enregistrer un pourcentage en utilisant 0-100 ou en utilisant 0-1. Ce qui importe, c'est ce que vous devez faire avec les chiffres, la précision dont vous avez besoin, etc. Vous devez expliquer plus de contexte avant de pouvoir donner une bonne réponse. Avez-vous besoin de stocker des nombres qui sont exactement représentables avec un petit nombre de chiffres décimaux? Si vous faites la moyenne des choses, vous obtenez des fractions comme les tiers ou les septièmes. Avez-vous besoin de les stocker exactement? Ou juste approximativement? À peu près? Qu'allez-vous en faire?
Eric Postpischil

1
Si les valeurs sont comprises entre 0,00 et 100,00 par pas de 0,01, cela signifie 10001 valeurs différentes. Utilisez simplement un intpour représenter les centièmes ou en unités de Permyriad ou ‱.
chux

@ chux-ReinstateMonica - Oui, des "entiers à l'échelle" sont possibles, mais maladroits.
Rick James

@RickJames Peut-être. Je n'ai pas trouvé difficile les entiers mis à l'échelle.
chux

Réponses:


4

Je vais prendre la position opposée.

FLOATest pour les nombres approximatifs, tels que les pourcentages, les moyennes, etc. Vous devez faire le formatage lorsque vous affichez les valeurs, soit dans le code de l'application, soit en utilisant la FORMAT()fonction de MySQL.

Ne testez jamais float_value = 1.3; il y a plusieurs raisons pour lesquelles cela échouera.

DECIMALdoit être utilisé pour les valeurs monétaires. DECIMALévite un deuxième arrondi lorsqu'une valeur doit être arrondie en dollars / cents / euros / etc. Les comptables n'aiment pas les fractions de cents.

L'implémentation de MySQL DECIMALautorise 65 chiffres significatifs; FLOATdonne environ 7 et DOUBLEenviron 16. 7 est généralement plus que suffisant pour les capteurs et les calculs scientifiques.

Quant au "pourcentage" - Parfois, je l'ai utilisé TINYINT UNSIGNEDquand je veux consommer seulement 1 octet de stockage et que je n'ai pas besoin de beaucoup de précision; parfois j'ai utilisé FLOAT(4 octets). Aucun type de données n'est réglé spécifiquement pour le pourcentage. (Notez également que DECIMAL(2,0)cela ne peut pas contenir la valeur 100, donc techniquement, vous en auriez besoin DECIMAL(3,0).)

Ou parfois, j'ai utilisé un FLOATqui détenait une valeur entre 0 et 1. Mais alors je devrais m'assurer de multiplier par 100 avant d'afficher le "pourcentage".

Plus

Les trois odeurs "pourcentage, moyenne, taux" comme des flotteurs, ce serait donc mon premier choix.

Un critère pour décider du type de données ... Combien de copies de la valeur existeront?

Si vous avez une table de milliards de lignes avec une colonne pour un pourcentage, considérez que TINYINTcela prendrait 1 octet (1 Go au total), mais FLOAT4 octets (4 Go au total). OTOH, la plupart des applications n'ont pas autant de lignes, donc cela peut ne pas être pertinent.

En règle générale, les valeurs "exactes" doivent utiliser une forme de INTou DECIMAL. Des choses inexactes (calculs scientifiques, racines carrées, division, etc.) devraient utiliser FLOAT(ou DOUBLE).

En outre, la mise en forme de la sortie doit généralement être laissée à l'interface de l'application. C'est-à-dire que même si une "moyenne" peut être calculée comme "14.6666666 ...", l'affichage devrait montrer quelque chose comme "14.7"; c'est plus convivial pour les humains. Pendant ce temps, vous avez la valeur sous-jacente pour décider plus tard que "15" ou "14,667" est le formatage de sortie préférable.

La plage "0,00 - 100,00" peut être effectuée soit avec FLOAT et utiliser le formatage de sortie, soit avec DECIMAL(5,2)(3 octets) avec la prédétermination que vous voudrez toujours la précision indiquée .


3

Je recommanderais généralement contre l'utilisation float. Les nombres à virgule flottante représentent des nombres en base-2, ce qui fait que certains nombres (exacts) sont arrondis dans les opérations ou les comparaisons, car ils ne peuvent tout simplement pas être stockés avec précision dans la base-2. Cela peut conduire à des comportements surprenants.

Prenons l'exemple suivant :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

La comparaison du nombre en base 2 1.3échoue. C'est délicat.

En comparaison, les décimales fournissent une représentation précise des nombres finis dans leur plage. Si vous passez floatà decimal(2, 1)dans l'exemple ci-dessus, vous obtenez les résultats attendus.


4
Cette réponse est fausse à plusieurs égards. «En comparaison, les décimales ont une plage plus petite mais fournissent une représentation exacte des nombres finis dans cette plage» est faux: la décimale ne représente pas exactement ⅓. «Certains nombres (exacts, finis) sont arrondis» est incorrect; les chiffres ne sont pas «arrondis». Les conversions et autres opérations peuvent être arrondies. Le mode d'arrondi par défaut est le plus souvent arrondi au plus proche-égal à égal, pas arrondi.
Eric Postpischil

4
Les problèmes de précision ne sont pas dus à des «nombres à virgule flottante» mais simplement à des représentations numériques: toutes les représentations numériques finies ont une précision limitée: virgule flottante, virgule fixe, entier, rationnel, décimal, binaire, tout.
Eric Postpischil

2
Soupir. Qu'avez-vous corrigé? Mon commentaire dit que la réponse est fausse car elle dit que le nombre décimal fournit une représentation exacte des nombres dans sa plage, mais en fait ce n'est pas le cas car il ne fournit pas une représentation exacte de ⅓. Le changement dit «précis» au lieu de «exact», mais alors pourquoi la virgule flottante binaire n'est-elle pas aussi bonne? ils ont. La question indique que les moyennes seront représentées, et la moyenne de trois choses vous donne des nombres comme ⅓.
Eric Postpischil

4
Le commentaire dit que l'arrondi au plus proche-à-pair est le plus couramment utilisé, mais la réponse dit toujours arrondi. La réponse dit que les comparaisons peuvent arrondir, mais la comparaison est parfaite: les comparaisons renvoient toujours un résultat mathématiquement correct, sans arrondi. (Certains langages de programmation peuvent convertir des opérandes avant de les comparer, mais ce sont des opérations distinctes.)
Eric Postpischil

1
1/3 ne peut pas être représenté exactement en binaire ou en décimal. Un rabais de 20% sur 14,99 $ exigera que les centimes fractionnaires d'arrondi n'existent pas.
Rick James

0

La différence entre float et decimal est la précision. Decimal peut représenter à 100% avec précision n'importe quel nombre dans la précision du format décimal, tandis que Float ne peut pas représenter avec précision tous les nombres.

Utilisez Decimal pour, par exemple, une valeur financière et utilisez float pour, par exemple, une valeur graphique


0

Je recommande d'utiliser decimal(5,2)si vous allez le stocker de la même manière que vous l'afficherez car decimalc'est pour préserver la précision exacte. (Voir https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

Comme les valeurs à virgule flottante sont approximatives et ne sont pas stockées en tant que valeurs exactes, les tentatives de les traiter comme exactes dans les comparaisons peuvent entraîner des problèmes. Ils sont également soumis à des dépendances de plateforme ou d'implémentation.

( https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html )

Une valeur à virgule flottante telle qu'écrite dans une instruction SQL peut ne pas être identique à la valeur représentée en interne.

Pour les colonnes DECIMAL, MySQL effectue des opérations avec une précision de 65 chiffres décimaux, ce qui devrait résoudre les problèmes d'inexactitude les plus courants.

https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html


0

Décimal: dans le cas d'applications financières, il est préférable d'utiliser les types décimaux car il vous offre un haut niveau de précision et permet d'éviter facilement les erreurs d'arrondi.

Double: les types doubles sont probablement le type de données le plus utilisé pour les valeurs réelles, sauf pour la gestion de l'argent.

Flottant: Il est principalement utilisé dans les bibliothèques graphiques, car les exigences très élevées en matière de puissance de traitement, ont également utilisé des situations qui peuvent supporter des erreurs d'arrondi.

Référence: http://net-informations.com/q/faq/float.html


0
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G

*********************************************************************

@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100

La décimale a fait exactement ce qui était censé faire sur ces cas, elle a tronqué le reste, perdant ainsi la partie 1/3.

Donc pour les sommes, la décimale est meilleure, mais pour les divisions, le flotteur est meilleur, jusqu'à un certain point, bien sûr. Je veux dire, l'utilisation de DECIMAL ne vous donnera en aucun cas une "arithmétique infaillible".

J'espère que cela vous aidera.


0

Dans tsql: Float, 0.0 stocke comme 0 et il n'est pas nécessaire de définir après le chiffre du point décimal, par exemple vous n'avez pas besoin d'écrire Float (4,2). Décimal, 0.0 stocke comme 0.0 et il a la possibilité de définir comme décimal (4,2), je suggère 0,00-1,00, en faisant cela, vous pouvez calculer la valeur de ce pourcentage sans multiplier par 100, et si vous déclarez, définissez le type de données de cette colonne en pourcentage comme MS Excel et d'autres vues de plate-forme comme 0.5 -> 50%.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.