Quelle différence cela fait-il lorsque j'utilise les types de données float et decimal dans mysql. Lequel est idéal pour l'utilisation.
Réponses
Trop de publicités?Ce site c'est ce que j'ai trouvé quand j'ai eu ce doute.
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
*************************** 1. row ***************************
@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 qu'elle est censée faire dans ce 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, la flottante est mieux, jusqu'à un certain point, bien sûr. Je veux dire que l'utilisation de DECIMAL ne vous donnera pas ne vous donnera en aucun cas une "arithmétique sans faille".
J'espère que cela vous aidera.
Dans la plupart des environnements, un "float" est un type binaire à virgule flottante. Il peut stocker avec précision des valeurs en base 2 (jusqu'à un certain point), mais ne peut pas stocker avec précision de nombreuses valeurs en base 10 (décimales). Les flottants sont plus appropriés pour les calculs scientifiques. Ils sont pas approprié pour la plupart des mathématiques orientées vers les affaires, et l'utilisation inappropriée des flottants vous mordra. De nombreuses valeurs décimales ne peuvent pas être représentées exactement en base 2. 0.1
ne peut pas, par exemple, et vous obtenez donc des résultats étranges comme 1.0 - 0.1 = 0.8999999
.
Les décimales stockent les nombres en base 10. Les décimaux sont un bon type pour la plupart des mathématiques commerciales (mais tout type "monétaire" intégré est plus approprié pour les calculs financiers), lorsque la plage de valeurs dépasse celle fournie par les types entiers et que des valeurs fractionnaires sont nécessaires. Les décimaux, comme leur nom l'indique, sont conçus pour les nombres en base 10 - ils peuvent stocker avec précision les valeurs décimales (encore une fois, jusqu'à un certain point).
MySQL a récemment changé la façon dont ils stockent le Type DECIMAL . Dans le passé, ils stockaient les caractères (ou nybbles) pour chaque chiffre composant une représentation ASCII (ou nybble) d'un nombre - par rapport à un entier de complément à deux, ou un dérivé de celui-ci.
Le format de stockage actuel pour DECIMAL est une série d'entiers de 1, 2, 3 ou 4 octets dont les bits sont concaténés pour créer un nombre en complément à deux avec un point décimal implicite, défini par vous, et stocké dans le schéma de la base de données lorsque vous déclarez la colonne et spécifiez sa taille DECIMAL et la position du point décimal.
À titre d'exemple, si vous prenez un int 32 bits, vous pouvez stocker n'importe quel nombre de 0 à 4 294 967 295. Cela ne couvrira de manière fiable que 999 999 999, donc si vous supprimez 2 bits et utilisez (1<<30 -1), vous ne perdrez rien. Couvrir tous les nombres à 9 chiffres avec seulement 4 octets est plus efficace que de couvrir 4 chiffres en 32 bits en utilisant 4 caractères ASCII, ou 8 chiffres nybbles. (un nybble est de 4 bits, permettant les valeurs 0-15, plus que ce qui est nécessaire pour 0-9, mais vous ne pouvez pas éliminer ce gaspillage en passant à 3 bits, parce que cela ne couvre que les valeurs 0-7)
L'exemple utilisé sur les docs en ligne de MySQL utilise DECIMAL(18,9) comme exemple. Il s'agit de 9 chiffres avant et 9 chiffres après le point décimal implicite, ce qui, comme expliqué ci-dessus, nécessite le stockage suivant.
Comme 18 caractères de 8 bits : 144 bits
Comme 18 nybbles de 4 bits : 72 bits
Comme 2 entiers de 32 bits : 64 bits
Actuellement, DECIMAL supporte un maximum de 65 chiffres, comme DECIMAL(M,D) où la plus grande valeur de M autorisée est 65, et la plus grande valeur de D autorisée est 30.
Pour ne pas avoir besoin de morceaux de 9 chiffres à la fois, des entiers inférieurs à 32 bits sont utilisés pour ajouter des chiffres en utilisant des entiers de 1, 2 et 3 octets. Pour une raison qui défie toute logique, des entiers signés, au lieu d'entiers non signés, ont été utilisés et, ce faisant, un bit est supprimé, ce qui donne les capacités de stockage suivantes. Pour les entiers de 1, 2 et 4 octets, le bit perdu n'a pas d'importance, mais pour l'entier de 3 octets, c'est un désastre car un chiffre entier est perdu à cause de la perte de ce seul bit.
Avec un int. de 7 bits : 0 - 99
Avec un int. de 15 bits : 0 - 9,999
Avec un int. de 23 bits : 0 - 999,999 (0 - 9,999,999 avec un int de 24 bits)
Les entrées de 1, 2, 3 et 4 bits sont concaténées ensemble pour former un "pool de bits" que DECIMAL utilise pour représenter le nombre précisément comme un entier de complément à deux. Le point décimal n'est PAS stocké, il est implicite.
Cela signifie qu'aucune conversion ASCII vers int n'est requise du moteur de BD pour convertir le "nombre" en quelque chose que le CPU reconnaît comme un nombre. Pas d'arrondi, pas d'erreur de conversion, c'est un vrai nombre que le CPU peut manipuler.
Les calculs sur ce nombre entier arbitrairement grand doivent être effectués par logiciel, car il n'existe pas de support matériel pour ce type de nombre, mais ces bibliothèques sont très anciennes et hautement optimisées, ayant été écrites il y a 50 ans pour supporter les données en virgule flottante de précision arbitraire d'IBM 370 Fortran. Elles sont toujours beaucoup plus lentes que l'algèbre des nombres entiers de taille fixe effectuée avec le matériel entier du CPU, ou que les calculs en virgule flottante effectués sur le FPU.
En termes d'efficacité de stockage, parce que l'exposant d'un flottant est attaché à chaque flottant, spécifiant implicitement où se trouve le point décimal, c'est massivement redondant, et donc inefficace pour le travail en BD. Dans une base de données, vous savez déjà à l'avance où le point décimal doit être placé, et chaque ligne de la table qui a une valeur pour une colonne DECIMAL n'a qu'à regarder la seule et unique spécification de l'endroit où ce point décimal doit être placé, stockée dans le schéma comme les arguments d'un DECIMAL(M,D) comme l'implication des valeurs M et D.
Les nombreuses remarques que l'on trouve ici sur le format à utiliser pour les différents types d'applications sont correctes, je ne vais donc pas insister sur ce point. J'ai pris le temps d'écrire ceci ici parce que la personne qui maintient la documentation en ligne de MySQL ne comprend rien de ce qui précède et après des séries de tentatives de plus en plus frustrantes pour le leur expliquer, j'ai abandonné. Une bonne indication de la mauvaise compréhension de ce qu'ils ont écrit est la présentation très confuse et presque indéchiffrable du sujet.
Pour terminer, si vous avez besoin d'un calcul en virgule flottante de haute précision, le code en virgule flottante a fait d'énormes progrès au cours des 20 dernières années, et le support matériel des codes à 96 bits et à 100 bits a été amélioré. Flotteur de quadruple précision sont à portée de main, mais il existe de bonnes bibliothèques de précision arbitraire si la manipulation de la valeur stockée est importante.
La différence entre les types flottants et décimaux est la façon dont ils représentent les valeurs fractionnaires, et n'est pas seulement spécifique à MySQL. Les types à virgule flottante représentent les fractions en binaire, ce qui ne peut représenter que les valeurs suivantes {m*2^n | m, n Integers}
. des valeurs telles que 1/5 ne peuvent être représentées avec précision (sans erreur d'arrondi). Les nombres décimaux sont limités de la même manière, mais représentent des nombres tels que {m*10^n | m, n Integers}
. Les décimales ne peuvent toujours pas représenter des nombres comme 1/3, mais dans de nombreux domaines courants, comme la finance, on s'attend à ce que certaines fractions décimales puissent toujours être exprimées sans perte de fidélité. Puisqu'un nombre décimal peut représenter une valeur comme $0.20
(un cinquième de dollar), il est préférable dans ces situations.