MySQL points Floating problèmes de comparaison
-
24-09-2019 - |
Question
Je suis tombé sur un problème en introduisant des colonnes à virgule flottante dans le schéma de base de données MySQL que les comparaisons sur les valeurs à virgule flottante ne renvoient pas les résultats corrects toujours.
1 à 50,12
2 - 34,57
3 - 12,75
4 - ... (tout repos inférieur à 12.00)
SELECT COUNT(*) FROM `users` WHERE `points` > "12.75"
Cela me retourne "3".
J'ai lu que les comparaisons de valeurs à virgule flottante dans MySQL est une mauvaise idée et le type décimal est la meilleure option.
Dois-je tout espoir d'aller de l'avant avec le flotteur et obtenir les comparaisons pour fonctionner correctement?
La solution
Avez-vous remarqué le problème ci-dessous?
CREATE TABLE a (num float);
INSERT INTO a VALUES (50.12);
INSERT INTO a VALUES (34.57);
INSERT INTO a VALUES (12.75);
INSERT INTO a VALUES (11.22);
INSERT INTO a VALUES (10.46);
INSERT INTO a VALUES (9.35);
INSERT INTO a VALUES (8.55);
INSERT INTO a VALUES (7.23);
INSERT INTO a VALUES (6.53);
INSERT INTO a VALUES (5.15);
INSERT INTO a VALUES (4.01);
SELECT SUM(num) FROM a;
+-----------------+
| SUM(num) |
+-----------------+
| 159.94000005722 |
+-----------------+
Il y a un écart de 0.00000005722
supplémentaire entre certaines de ces lignes. Par conséquent, certaines de ces valeurs renvoie false par rapport à la valeur qu'ils ont été initialisés avec.
Pour éviter des problèmes arithmétiques à virgule flottante et les comparaisons, vous devez utiliser le type de données DECIMAL
:
ALTER TABLE a MODIFY num DECIMAL(6,2);
SELECT SUM(num) FROM a;
+----------+
| SUM(num) |
+----------+
| 159.94 |
+----------+
1 row in set (0.00 sec)
Autres conseils
Je l'ai fait face à la même question une fois. Convertir le champ « float » à « décimale ». Il va certainement résoudre le problème.
Je le fais
WHERE abs(value - 12.75)<0.001
mais je suis d'accord, toute langue peut comparer flotter l'égalité et il ne doit pas si les valeurs stockées égal nombre exact que vous valeurs que vous avez inséré, comme toute question
avec seulement deux décimales et les valeurs de correspondance exacte, des erreurs de précision ne pas les sons comme une raison évidente pour de telles discordances dans MySQL
Il est un point flottant, alors quel est le problème? 3 pourrait être le résultat correct, dépend de ce que la base de données pense à 12,75. Est-il ou 12,75 juste un peu plus?
Utilisez DECIMAL si vous voulez des chiffres exacts.
Il y a un problème avec la comparaison des flotteurs pour l'égalité. Cela peut donner des résultats imprévus. Cela est dû à la mise en œuvre interne de point flottant Arithmétique.
En comparant un numéro avec une chaîne?
Utilisez REAL au lieu de FLOAT ou DECIMAL.