Почему MySQL Round плавает намного больше, чем ожидалось?
UPDATE some_table SET some_float_field=1919.987 WHERE id=123
SELECT * FROM some_table WHERE id=123
где some_float_field - это поле, определенное как "float" (без каких-либо конкретных значений размера).
Ожидаемое итоговое значение будет 1919,987; вместо этого он округляется до 1919,99
Зачем? 32-битное (одинарная точность) число с плавающей точкой имеет достаточную точность для правильного хранения!
2 ответа
Когда вы запускаете запрос:
SELECT * FROM some_table WHERE id = 123
Вы полагаетесь на пользовательский интерфейс для форматирования чисел с плавающей запятой. Интерфейс, который вы используете, использует два символа, а не больше. Ведь нет никакой информации о "правильном" номере для показа.
Вы можете убедить интерфейс показать правильное число, отформатировав число в виде строки или десятичного числа. Например:
select format(some_float_field, 3)
преобразует это в строку с тремя десятичными разрядами. Одно предостережение: он также добавит запятые, которые вы можете не захотеть. Это также должно работать:
select cast(some_float_field as decimal(8, 3))
также должен сделать свое дело.
Обратите внимание, что вы можете легко проверить правильность данных, выполнив что-то вроде:
select *
from some_table
where some_float_field between 1919.987 - 0.0001 and 1919.987 + 0.0001;
Обратите внимание, что вы не хотите использовать =
на значениях с плавающей запятой, но вы уже это понимаете.
Из руководства FLOAT
:
FLOAT
а такжеDOUBLE
типы представляют приблизительные числовые значения данных. MySQL использует четыре байта для значений одинарной точности.
Упор здесь лежит на приблизительный. Если вам нужно хранить точные значения, вы должны использовать DECIMAL
тип данных.
Обратите внимание, что это применяется к любому значению, независимо от того, может ли значение (десятичная часть и дробь) быть точно представлено в 4 байтах! Например, представление 0,01 в плавающей запятой в точности равно 0,009999999776482582092285156250 - даже если 0,01 идеально поместится в 32-разрядной памяти, используя другой формат хранения.
Википедия довольно хорошо объясняет концепцию с плавающей точкой.
Обратите внимание, что на алгоритм влияет точность, указанная в определении столбца.
Посмотрите этот пример SQL-скрипки.