Me encontré con este problema en el que insertar un número como 1234567 en una columna flotante conduce a un valor redondeado de 1234570 .
Entiendo que esto se debe a la precisión del punto flotante, pero lo que me confunde es que si hago algún cálculo con la columna flotante anterior, entonces usa el valor real (1234567).
Si solo uso una declaración Select en la columna, da el valor redondeado, pero si la paso a decimal o realizo algunos cálculos, lo hace con el valor real.
Entonces mi pregunta es ¿qué hace que MySQL actúe así?
EDITAR:
Por ejemplo:
select cast(1234567 as float), cast(1234567 as float) + 1devoluciones:
1234570 1234568Aquí hay un db<>fiddle.
Su pregunta sobre la precisión del punto flotante no se limita realmente a MySQL, es una pregunta válida y similar para cualquier base de datos o lenguaje de programación. La conclusión es que debido a la forma en que los flotadores se representan internamente, no son exactos, ni la aritmética se hace con flotadores exactos.
Si necesita una precisión exacta, entonces debería usar un tipo exacto como NUMERIC o DECIMAL .
De acuerdo con la receta , podemos obtener tipos de datos en su violín, y se muestra (lo ejecuto en 8.0.20/FreeBSD/i386):
netch@localhost [test]> create temporary table t1 select cast(1234567 as float), cast(1234567 as float) + 1, cast(12345678 as float) + 1; netch@localhost [test]> show create table t1; +-------+----------------------------------------------------------------------> | Table | Create Table > +-------+----------------------------------------------------------------------> | t1 | CREATE TEMPORARY TABLE `t1` ( `cast(1234567 as float)` float NOT NULL DEFAULT '0', `cast(1234567 as float) + 1` double NOT NULL DEFAULT '0', `cast(12345678 as float) + 1` double NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci | +-------+----------------------------------------------------------------------> 1 row in set (0.00 sec) por lo que sus tipos de reglas dan como resultado float en un caso y double en otro caso. 1234567 se representa exactamente en float, pero vea a continuación para truncar.
Los experimentos muestran que CAST (AS float) proporciona un valor flotante float64 ( double en C) mientras está marcado como float pero el valor real se corta a float32 solo cuando finalmente se coloca en la celda DB almacenada. Pero, con '+', float se convierte en double antes de agregar y esto se denota además como resultado del tipo de operador, por lo que la creación automática expone double . Pero si el tipo declarado permanece flotante, MySQL no solo lo trunca a float32, sino que lo redondea a 6 dígitos imprimibles predeterminados :(
No puedo encontrar estos detalles en la documentación de MySQL (o esto se omite o tengo malas habilidades de excavación para este estilo de documentación), pero este enfoque (excepto el corte en forma de texto) al menos se ajusta a la forma de sentido común aplicada a C/C++. Permiten tener una representación intermedia más amplia de valores flotantes antes de colocar las variables de salida.
Como tal, CAST() es nuevo para 8.0 (5.7 no era compatible con float y double in casts), es probable que se trate de una implementación demasiado cruda. Siéntase libre de quejarse con los desarrolladores de MySQL para avanzar a un modo adecuado.