Diferencia entre el tipo de datos flotante y decimal


¿Qué diferencia hace cuando uso tipos de datos flotantes y decimales en MySQL?.

¿Cuándo debo usar cuál?

 164
Author: Inigo Flores, 2011-03-01

13 answers

Esto es lo que encontré cuando tuve esta duda.

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

El decimal hizo exactamente lo que se supone que debe hacer en estos casos, truncado el resto, perdiendo así la 1/3 parte.

Así que para sumas el decimal es mejor, pero para divisiones el flotador es mejor, hasta cierto punto, por supuesto. Quiero decir, usar DECIMAL no dará eres una "aritmética a prueba de fallos" en cualquier medio.

Espero que esto ayude.

 174
Author: kanap008,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-01 07:32:01

Un "float" en la mayoría de los entornos es un tipo de punto flotante binario. Puede almacenar con precisión valores base - 2 (hasta cierto punto), pero no puede almacenar con precisión muchos valores base-10 (decimales). Los flotadores son los más apropiados para los cálculos científicos. Son no apropiados para la mayoría de las matemáticas orientadas a los negocios, y el uso inapropiado de carrozas te morderá. Muchos valores decimales no se pueden representar exactamente en base-2. 0.1 no puede, por ejemplo, y así se ven resultados extraños como 1.0 - 0.1 = 0.8999999.

Los decimales almacenan números base-10. Decimal es un buen tipo para la mayoría de las matemáticas de negocios (pero cualquier tipo de "dinero" incorporado es más apropiado para los cálculos financieros), donde el rango de valores excede el proporcionado por los tipos enteros, y se necesitan valores fraccionarios. Los decimales, como su nombre lo indica, están diseñados para números base-10-que pueden almacenar con precisión los valores decimales (de nuevo, a un cierto punto).

 72
Author: Michael Petrotta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-19 00:56:28

MySQL cambió recientemente su forma de almacenar el tipo DECIMAL . En el pasado almacenaban los caracteres (o nybbles) para cada dígito que comprendía una representación ASCII (o nybble) de un número - vs - un número entero de complemento de dos, o algún derivado del mismo.

El formato de almacenamiento actual para DECIMAL es una serie de enteros de 1,2,3 o 4 bytes cuyos bits se concatenan para crear un número de complemento de dos con un punto decimal implícito, definido por usted, y almacenado en el esquema DB cuando declare la columna y especifique su tamaño DECIMAL y posición de punto decimal.

A modo de ejemplo, si toma un int de 32 bits, puede almacenar cualquier número de 0 a 4,294,967,295. Eso solo cubrirá de manera confiable 999,999,999, por lo que si tiraste 2 bits y usaste (1

El ejemplo usado en los documentos en línea de MySQL usa DECIMAL(18,9) como ejemplo. Esto es 9 dígitos por delante y 9 dígitos por detrás del punto decimal implícito, que como se explicó anteriormente requiere el siguiente almacenamiento.

Como 18 caracteres de 8 bits: 144 bits

Como 18 nybbles de 4 bits: 72 bits

Como 2 enteros de 32 bits: 64 bits

Actualmente DECIMAL soporta un máximo de 65 dígitos, como DECIMAL (M,D) donde el mayor valor para M permitido es 65, y el mayor valor de D permitido es 30.

Para no requerir trozos de 9 dígitos a la vez, los enteros más pequeños que 32 bits se utilizan para agregar dígitos utilizando enteros de 1,2 y 3 bytes. Por alguna razón que desafía la lógica, se usaron INT firmados, en lugar de INT sin firmar, y al hacerlo, se elimina 1 bit, lo que resulta en las siguientes capacidades de almacenamiento. Para 1,2 y 4 bytes ints el bit perdido no importa, pero para el 3-byte int es un desastre porque se pierde un dígito entero debido a la pérdida de ese solo bit.

Con una int de 7 bits: 0 - 99

Con una int de 15 bits: 0 - 9,999

Con una int de 23 bits: 0 - 999,999 (0 - 9,999,999 con un int de 24 bits)

Los enteros de 1,2,3 y 4 bytes se concatenan juntos para formar un "conjunto de bits" DECIMAL que se usa para representar el número con precisión como un entero de complemento de dos. El punto decimal NO se almacena, está implícito.

Esto significa que no hay ASCII para int se requieren conversiones del motor de base de datos para convertir el" número " en algo que la CPU reconoce como un número. Sin redondeo, sin errores de conversión, es un número real que la CPU puede manipular.

Los cálculos sobre este entero arbitrariamente grande deben hacerse en software, ya que no hay soporte de hardware para este tipo de número, pero estas bibliotecas son muy antiguas y altamente optimizadas, habiendo sido escritas hace 50 años para soportar datos de punto flotante de precisión arbitraria de IBM 370 Fortran. Todavía son mucho más lentos que el álgebra de enteros de tamaño fijo hecho con hardware de enteros de CPU, o los cálculos de coma flotante hechos en la FPU.

En términos de eficiencia de almacenamiento, debido a que el exponente de un flotador está unido a todos y cada uno de los flotadores, especificando implícitamente dónde está el punto decimal, es masivamente redundante y, por lo tanto, ineficiente para el trabajo de base de datos. En una BD ya sabes dónde va a ir el punto decimal, y cada fila de la tabla que tiene un valor para un DECIMAL columna solo necesita mirar la especificación 1 & only de dónde se colocará ese punto decimal, almacenado en el esquema como los argumentos a un DECIMAL (M,D) como la implicación de los valores M y D.

Las muchas observaciones que se encuentran aquí sobre qué formato se debe usar para varios tipos de aplicaciones son correctas, por lo que no voy a abundar en el punto. Me tomé el tiempo para escribir esto aquí porque quienquiera que esté manteniendo la documentación en línea de MySQL vinculada no entiende nada de lo anterior y después rondas de intentos cada vez más frustrantes para explicárselo me rendí. Una buena indicación de lo mal que entendían lo que estaban escribiendo es la presentación muy confusa y casi indescifrable del tema.

Como pensamiento final, si usted tiene necesidad de computación de punto flotante de alta precisión, ha habido enormes avances en el código de punto flotante en los últimos 20 años, y el soporte de hardware para 96 bits y Quadruple Precision float están alrededor del esquina, pero hay buenas bibliotecas de precisión arbitraria por ahí si la manipulación del valor almacenado es importante.

 19
Author: user2548100,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-29 18:56:59

No solo es específico de MySQL, la diferencia entre los tipos float y decimal es la forma en que representan valores fraccionarios. Los tipos de coma flotante representan fracciones en binario, que solo pueden representar valores como {m*2^n | m, n Integers}. valores como 1/5 no se pueden representar con precisión (sin error de redondeo). Los números decimales son similarmente limitados, pero representan números como {m*10^n | m, n Integers}. Los decimales todavía no pueden representar números como 1/3, pero a menudo es el caso en muchos campos comunes, como las finanzas, que la expectativa es que ciertas fracciones decimales siempre se puedan expresar sin pérdida de fidelidad. Dado que un número decimal puede representar un valor como $0.20 (una quinta parte de un dólar), se prefiere en esas situaciones.

 12
Author: SingleNegationElimination,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-01 04:00:19

Decimal es para cantidades fijas como dinero donde desea un número específico de lugares decimales. Los flotadores son para almacenar ... números de precisión de punto flotante.

 9
Author: Skylar Saveland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-01 03:57:36
mysql> CREATE TABLE num(id int ,fl float,dc dec(5,2));
Query OK, 0 rows affected (0.00 sec)


mysql> INSERT INTO num VALUES(1,13.75,13.75);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO num VALUES(2,13.15,13.15);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM num WHERE fl = 13.15;
Empty set (0.00 sec)

mysql> SELECT * FROM num WHERE dc = 13.15;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)

mysql> SELECT SUM(fl) ,SUM(dc)  FROM num;
+--------------------+---------+
| SUM(fl)            | SUM(dc) |
+--------------------+---------+
| 26.899999618530273 |   26.90 |
+--------------------+---------+
1 row in set (0.00 sec)


mysql> SELECT * FROM num WHERE ABS(fl -  13.15)<0.01;
+------+-------+-------+
| id   | fl    | dc    |
+------+-------+-------+
|    2 | 13.15 | 13.15 |
+------+-------+-------+
1 row in set (0.00 sec)
 5
Author: zloctb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-25 07:23:53

Flotador:

Un número de coma flotante pequeño (de una sola precisión). Los valores permitidos son -3.402823466 E + 38 a -1.175494351 E-38,0, y 1.175494351 E-38 a 3.402823466 E+38. Estos son los límites teóricos, basados en el estándar IEEE. El rango real puede ser ligeramente más pequeño dependiendo de su hardware o sistema operativo.

DECIMAL:

Un número de punto fijo "exacto" empaquetado. M es el número total de dígitos (la precisión) y D es el número de dígitos después del punto decimal (escala). El punto decimal y (para números negativos) el signo " - " no se cuenta inM. Si D es 0, los valores no tienen punto decimal o parte fraccionaria. El número máximo de dígitos (M) para el DECIMAL es 65. El número máximo de decimales admitidos D) is 30. Si se omite D, el valor predeterminado es 0. Si se omite M, el valor predeterminado es 10.

 4
Author: Iren Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-19 11:50:19

Encontré esto útil:

Generalmente, los valores flotantes son buenos para Cálculos científicos, pero no deben usarse para Valores Financieros/Monetarios. Para Las Matemáticas Orientadas a los Negocios, siempre use Decimal.

Fuente: http://code.rohitink.com/2013/06/12/mysql-integer-float-decimal-data-types-differences/

 4
Author: Tuomo B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-15 12:17:08

Si buscas rendimiento y no precisión, debes tener en cuenta que los cálculos con flotadores son mucho más rápidos que los decimales

 2
Author: Semra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-20 21:28:59

Tipos de Coma Flotante (Valor Aproximado) - FLOAT, DOUBLE

Los tipos FLOAT y DOUBLE representan valores aproximados de datos numéricos. MySQL utiliza cuatro bytes para valores de precisión simple y ocho bytes para valores de precisión doble.

Para FLOAT, el estándar SQL permite una especificación opcional de la precisión (pero no el rango del exponente) en bits después de la palabra clave FLOAT entre paréntesis. MySQL también admite esta especificación de precisión opcional, pero el valor de precisión se utiliza solo para determinar el tamaño de almacenamiento. Una precisión de 0 a 23 resulta en una columna FLOTANTE de una sola precisión de 4 bytes. Una precisión de 24 a 53 resulta en una columna de doble precisión de 8 bytes.

MySQL permite una sintaxis no estándar: FLOAT(M,D) o REAL(M,D) o DOUBLE PRECISION(M,D). Aquí," (M, D) " significa que los valores pueden almacenarse con hasta M dígitos en total, de los cuales D dígitos pueden estar después del punto decimal. Por ejemplo, una columna definida como FLOAT(7,4) se verá como -999.9999 cuando se muestra. MySQL realiza el redondeo al almacenar valores, por lo que si inserta 999.00009 en una columna FLOTANTE(7,4), el resultado aproximado es 999.0001.

Debido a que los valores de coma flotante son aproximados y no se almacenan como valores exactos, los intentos de tratarlos como exactos en las comparaciones pueden dar lugar a problemas. También están sujetos a dependencias de plataforma o implementación.

Para la máxima portabilidad, el código que requiere el almacenamiento de valores de datos numéricos aproximados debe utilizar FLOTADOR o DOBLE PRECISIÓN sin especificación de precisión o número de dígitos.

Https://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html

Problemas con los Valores de Coma Flotante

Los números de coma flotante a veces causan confusión porque son aproximados y no se almacenan como valores exactos. Un valor de coma flotante escrito en una sentencia SQL puede no ser el mismo que el valor representado internamente. Intentos de tratar los valores de coma flotante como exactos en las comparaciones pueden dar lugar a problemas. También están sujetos a dependencias de plataforma o implementación. Los tipos de datos FLOAT y DOUBLE están sujetos a estos problemas. Para las columnas DECIMALES, MySQL realiza operaciones con una precisión de 65 dígitos decimales, lo que debería resolver los problemas de inexactitud más comunes.

El siguiente ejemplo utiliza DOUBLE para demostrar cómo los cálculos que se realizan utilizando operaciones de coma flotante están sujetos a coma flotante error.

mysql> CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
mysql> INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
    -> (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
    -> (2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
    -> (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
    -> (5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
    -> (6, 0.00, 0.00), (6, -51.40, 0.00);

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b
    -> FROM t1 GROUP BY i HAVING a <> b;

+------+-------+------+
| i    | a     | b    |
+------+-------+------+
|    1 |  21.4 | 21.4 |
|    2 |  76.8 | 76.8 |
|    3 |   7.4 |  7.4 |
|    4 |  15.4 | 15.4 |
|    5 |   7.2 |  7.2 |
|    6 | -51.4 |    0 |
+------+-------+------+

El resultado es correcto. Aunque los primeros cinco registros parecen no satisfacer la comparación (los valores de a y b no parecen ser diferentes), pueden hacerlo porque la diferencia entre los números se muestra alrededor del décimo decimal más o menos, dependiendo de factores como la arquitectura de la computadora o la versión del compilador o el nivel de optimización. Por ejemplo, diferentes CPU pueden evaluar números de coma flotante de manera diferente.

Si las columnas d1 y d2 hubieran sido definido como DECIMAL en lugar de DOBLE, el resultado de la consulta SELECT habría contenido solo una fila, la última que se muestra arriba.

La forma correcta de hacer la comparación de números en coma flotante es primero decidir una tolerancia aceptable para las diferencias entre los números y luego hacer la comparación contra el valor de tolerancia. Por ejemplo, si estamos de acuerdo en que los números de coma flotante deben considerarse iguales si son iguales dentro de una precisión de uno en diez mil (0.0001), la comparación debe escribirse para encontrar diferencias mayores que el valor de tolerancia:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+-------+------+
| i    | a     | b    |
+------+-------+------+
|    6 | -51.4 |    0 |
+------+-------+------+
1 row in set (0.00 sec)

Por el contrario, para obtener filas donde los números son los mismos, la prueba debe encontrar diferencias dentro del valor de tolerancia:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
    -> GROUP BY i HAVING ABS(a - b) <= 0.0001;
+------+------+------+
| i    | a    | b    |
+------+------+------+
|    1 | 21.4 | 21.4 |
|    2 | 76.8 | 76.8 |
|    3 |  7.4 |  7.4 |
|    4 | 15.4 | 15.4 |
|    5 |  7.2 |  7.2 |
+------+------+------+
5 rows in set (0.03 sec)

Los valores de coma flotante están sujetos a dependencias de plataforma o implementación. Supongamos que ejecuta las siguientes instrucciones:

CREATE TABLE t1(c1 FLOAT(53,0), c2 FLOAT(53,0));
INSERT INTO t1 VALUES('1e+52','-1e+52');
SELECT * FROM t1;

En algunas plataformas, la instrucción SELECT devuelve inf y-inf. En otros, devuelve 0 y -0.

Una implicación de el problema anterior es que si intenta crear un esclavo de replicación descargando el contenido de la tabla con mysqldump en el maestro y recargando el archivo de volcado en el esclavo, las tablas que contienen columnas de punto flotante pueden diferir entre los dos hosts.

Https://dev.mysql.com/doc/refman/5.5/en/problems-with-float.html

 1
Author: Think Big,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-15 15:09:12

Regla dura y rápida

Si todo lo que necesita hacer es sumar, restar o multiplicar los números que está almacenando, DECIMAL es lo mejor.

Si necesita dividir o hacer cualquier otra forma de aritmética o álgebra en los datos, es casi seguro que será más feliz con float. Las bibliotecas de coma flotante, y en los procesadores Intel, el propio procesador de coma flotante, tienen toneladas de operaciones para corregir, reparar, detectar y manejar la tormenta de excepciones que se producen al hacer funciones matemáticas - especialmente funciones trascendentales.

En cuanto a la precisión, una vez escribí un sistema de presupuesto que calculaba la contribución % de cada una de las 3,000+ cuentas, para 3,600 unidades de presupuesto, por mes al nodo de consolidación de esa unidad, luego basado en esa matriz de porcentajes (3,000 + x 12 x 3,600) Multiplicé las cantidades presupuestadas por los nodos organizacionales más altos hasta los siguientes 3 niveles de los nodos organizacionales, y luego calculé todos (3,000 + 12) valores para todas las 3,200 unidades de detalle de eso. Millones y millones y millones de cálculos de punto flotante de doble precisión, cualquiera de los cuales arrojaría el enrollamiento de todas esas proyecciones en una consolidación ascendente de vuelta al nivel más alto de la organización.

El error total de coma flotante después de todos esos cálculos fue CERO. Eso fue en 1986, y las bibliotecas de coma flotante hoy en día son mucho, mucho mejores de lo que eran entonces. Intel hace todos sus cálculos intermedios de se duplica en precisión de 80 bits, lo que prácticamente elimina el error de redondeo. Cuando alguien te dice "es un error de punto flotante" es casi seguro que NO es cierto.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-20 19:48:40

float (y double) representa fracciones binarias

decimal representa fracciones decimales

 -1
Author: ReignBough,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-04 04:58:11
declare @float as float(10)
declare @Decimal as decimal(10)
declare @Inetger as int

set @float =10.7
set @Decimal =10.7
set @Inetger=@Decimal

print @Inetger

En coma flotante cuando se establece el valor en entero imprimir 10 pero en decimal 11

 -2
Author: user966380,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-19 11:35:24