Проблемы сравнения MySQL с плавающей запятой - PullRequest
20 голосов
/ 02 апреля 2010

Я столкнулся с проблемой, введя столбцы с плавающей запятой в схему базы данных MySQL, чтобы сравнения значений с плавающей запятой не всегда возвращали правильные результаты.

1 - 50,12
2 - 34,57
3 - 12,75
4 - ... (все остальные менее 12.00)

SELECT COUNT(*) FROM `users` WHERE `points` > "12.75"

Это возвращает мне "3".

Я читал, что сравнение значений с плавающей запятой в MySQL - плохая идея, и лучше использовать десятичный тип.

Есть ли у меня надежда продвинуться с типом float и заставить сравнения работать правильно?

Ответы [ 7 ]

25 голосов
/ 02 апреля 2010

Вы заметили проблему ниже?

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 | 
+-----------------+

Существует дополнительный 0.00000005722 спред между некоторыми из этих строк. Поэтому некоторые из этих значений будут возвращать false при сравнении со значением, с которым они были инициализированы.

Чтобы избежать проблем с арифметикой с плавающей точкой и сравнениями, вы должны использовать тип данных 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)
2 голосов
/ 07 апреля 2017

Я делаю это

WHERE abs(value - 12.75)<0.001

но я согласен, любой язык может сравнивать равенство с плавающей запятой, и если сохраненные значения равны точным числам, которые вы вставили, проблем не должно быть

только с несколькими десятичными знаками и точными совпадающими значениями, ошибки точности не кажутся очевидной причиной таких несоответствий в MySQL

2 голосов
/ 05 апреля 2010

Однажды я столкнулся с подобной проблемой. Преобразуйте поле с плавающей запятой в десятичное. Это определенно решит проблему.

1 голос
/ 02 апреля 2010

Есть проблемы со сравнением поплавков на равенство. Это может дать непредсказуемые результаты. Это связано с внутренней реализацией арифметики с плавающей запятой.

1 голос
/ 02 апреля 2010

Это с плавающей точкой, так в чем же проблема? 3 может быть правильным результатом, зависит от того, что база данных думает о 12.75. Это 12,75 или чуть больше?

Используйте DECIMAL, если хотите точные цифры.

0 голосов
/ 26 июня 2019

Используйте REAL вместо FLOAT или DECIMAL.

0 голосов
/ 02 апреля 2010

Сравнение числа со строкой?

...