Cuándo usar float vs decimal


14

Estoy creando esta API, y la base de datos almacenará valores que representan uno de los siguientes:

  • porcentaje
  • promedio
  • Velocidad

Sinceramente, no tengo idea de cómo representar algo con un rango entre 0 y 100% en números. Deberia ser

  • 0.00 - 1.00
  • 0.00 - 100.00
  • cualquier otra alternativa que no conozco

¿Hay una opción clara para eso? ¿Una forma global de representar en bases de datos algo que va del 0 al 100% por ciento? Yendo más lejos, ¿cuál es el tipo correcto para él, flotante o decimal?

Gracias.



55
Los números pueden almacenarse de muchas maneras. No hay nada inherentemente malo en almacenar un porcentaje usando 0-100 o usando 0-1. Lo que importa es lo que necesita hacer con los números, la precisión que necesita, etc. Debe explicar más contexto antes de poder dar una buena respuesta. ¿Necesita almacenar números que sean exactamente representables con un pequeño número de dígitos decimales? Si promedias cosas, obtienes fracciones como tercios o séptimos. ¿Necesitas guardarlos exactamente? O solo aproximadamente? ¿Cómo aproximadamente? ¿Qué vas a hacer con ellos?
Eric Postpischil

1
Si los valores son 0.00 a 100.00 en pasos de 0.01, eso es 10001 valores diferentes. Simplemente use un intpara representar centésimos o en unidades de Permyriad o ‱.
chux - Restablece a Monica el

@ chux-ReinstateMonica - Sí, los "enteros escalados" son posibles, pero torpes.
Rick James

@RickJames Quizás. No he encontrado números enteros escalados difíciles.
chux - Restablece a Mónica el

Respuestas:


4

Tomaré la postura opuesta.

FLOATes para números aproximados, como porcentajes, promedios, etc. Debe formatear mientras muestra los valores, ya sea en el código de la aplicación o usando la FORMAT()función de MySQL.

Nunca pruebes float_value = 1.3; Hay muchas razones por las que eso fallará.

DECIMALdebe usarse para valores monetarios. DECIMALevita un segundo redondeo cuando un valor debe redondearse a dólares / centavos / euros / etc. A los contadores no les gustan las fracciones de centavos.

La implementación de MySQL DECIMALpermite 65 dígitos significativos; FLOATda aproximadamente 7 y DOUBLEaproximadamente 16. 7 es generalmente más que suficiente para sensores y cálculos científicos.

En cuanto al "porcentaje": a veces lo he usado TINYINT UNSIGNEDcuando quiero consumir solo 1 byte de almacenamiento y no necesito mucha precisión; a veces he usado FLOAT(4 bytes). No hay ningún tipo de datos ajustado específicamente para el porcentaje. (Tenga en cuenta también que DECIMAL(2,0)eso no puede contener el valor 100, por lo que técnicamente necesitaría DECIMAL(3,0)).

O, a veces, he usado un FLOATvalor que tenía un valor entre 0 y 1. Pero tendría que asegurarme de multiplicar por 100 antes de mostrar el "porcentaje".

Más

Los tres "porcentaje, promedio, tasa" huelen a flotadores, así que esa sería mi primera opción.

Un criterio para decidir el tipo de datos ... ¿Cuántas copias del valor existirán?

Si tiene una tabla de mil millones de filas con una columna para un porcentaje, considere que TINYINTtomaría 1 byte (1 GB en total), pero FLOATtomaría 4 bytes (4 GB en total). OTOH, la mayoría de las aplicaciones no tienen tantas filas, por lo que esto puede no ser relevante.

Como regla 'general', los valores "exactos" deben usar alguna forma de INTo DECIMAL. Las cosas inexactas (cálculos científicos, raíces cuadradas, división, etc.) deben usar FLOAT(o DOUBLE).

Además, el formato de la salida generalmente se debe dejar al front-end de la aplicación. Es decir, a pesar de que un "promedio" puede calcular a "14.6666666 ...", la pantalla debería mostrar algo así como "14.7"; Esto es más amigable para los humanos. Mientras tanto, tiene el valor subyacente para decidir más tarde que "15" o "14.667" es el formato de salida preferible.

El rango "0.00 - 100.00" se puede hacer con FLOAT y utilizando el formato de salida o con DECIMAL(5,2)(3 bytes) con la determinación previa de que siempre querrá la precisión indicada .


3

En general, recomendaría no usar float. Los números de coma flotante representan números en base-2, lo que hace que algunos números (exactos) se redondeen en operaciones o comparaciones, porque simplemente no pueden almacenarse con precisión en base-2. Esto puede conducir a comportamientos sorprendentes.

Considere el siguiente ejemplo :

create table t (num float);
insert into t values(1.3);

select * from t;

| num |
| --: |
| 1.3 |

select * from t where num = 1.3;

| num |
| --: |

La comparación de base 2 del número 1.3falla. Esto es complicado

En comparación, el decimal proporciona una representación precisa de números finitos dentro de su rango. Si cambia floata decimal(2, 1)en el ejemplo anterior, obtendrá los resultados esperados.


44
Esta respuesta es falsa en varios aspectos. "En comparación, los decimales tienen un rango menor pero proporcionan una representación exacta de los números finitos dentro de ese rango" es falso: el decimal no representa exactamente ⅓. "Algunos números (exactos, finitos) son redondeados" es incorrecto; los números no son "redondeados". Las conversiones y otras operaciones pueden redondearse. El modo de redondeo predeterminado es más comúnmente redondear a lazos más cercanos a pares, no redondear.
Eric Postpischil

44
Los problemas con la precisión no se deben a los "números de punto flotante", sino simplemente a las representaciones numéricas: todas las representaciones numéricas finitas tienen una precisión limitada: punto flotante, punto fijo, entero, racional, decimal, binario, todo.
Eric Postpischil

2
Suspiro. ¿Qué has arreglado? Mi comentario dice que la respuesta es incorrecta porque dice que el decimal proporciona una representación exacta de los números dentro de su rango, pero en realidad no lo hace porque no proporciona una representación exacta de ⅓. El cambio dice "exacto" en lugar de "exacto", pero entonces, ¿por qué no es tan bueno el punto flotante binario? Ninguno es exacto para ⅓, y ambos o ninguno son exactos, dependiendo de cuál sea su umbral de precisión y cuánta precisión ellos tienen. La pregunta indica que se representarán promedios, y promediar tres cosas le da números como ⅓.
Eric Postpischil

44
El comentario dice que se usa con mayor frecuencia el redondeo al empate más cercano, pero la respuesta aún dice redondeo. La respuesta dice que las comparaciones pueden redondearse, pero las comparaciones son perfectas: las comparaciones siempre devuelven un resultado matemáticamente correcto, sin redondeo. (Algunos lenguajes de programación pueden convertir operandos antes de comparar, pero esas son operaciones separadas.)
Eric Postpischil

1
1/3 no puede representarse exactamente en binario o decimal. Un descuento del 20% de descuento de $ 14.99 requerirá redondear centavos fraccionales no existen.
Rick James

0

La diferencia entre flotante y decimal es la precisión. Decimal puede representar 100% con precisión cualquier número dentro de la precisión del formato decimal, mientras que Float no puede representar con precisión todos los números.

Use Decimal para, por ejemplo, el valor financiero relacionado y use flotante para, por ejemplo, el valor gráfico relacionado


0

Recomiendo usarlo decimal(5,2)si lo va a almacenar de la misma manera que lo mostrará, ya que decimales para preservar la precisión exacta. (Ver https://dev.mysql.com/doc/refman/8.0/en/fixed-point-types.html )

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

( https://dev.mysql.com/doc/refman/8.0/en/floating-point-types.html )

Un valor de coma flotante tal como está escrito en una declaración SQL puede no ser el mismo que el valor representado internamente.

Para columnas DECIMAL, MySQL realiza operaciones con una precisión de 65 dígitos decimales, lo que debería resolver los problemas de imprecisión más comunes.

https://dev.mysql.com/doc/refman/8.0/en/problems-with-float.html


0

Decimal: en el caso de las aplicaciones financieras, es mejor usar tipos Decimal porque le brinda un alto nivel de precisión y es fácil evitar errores de redondeo

Doble: los tipos dobles son probablemente el tipo de datos más utilizado para valores reales, excepto el manejo de dinero.

Flotante: se utiliza principalmente en bibliotecas gráficas porque las demandas de potencia de procesamiento son muy altas, también se utilizan situaciones que pueden soportar errores de redondeo.

Referencia: http://net-informations.com/q/faq/float.html


0
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

*********************************************************************

@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, truncó el resto, perdiendo así la parte 1/3.

Entonces, para las sumas, el decimal es mejor, pero para las divisiones, el flotador es mejor, hasta cierto punto, por supuesto. Quiero decir, usar DECIMAL no te dará "aritmética a prueba de fallas" de ninguna manera.

Espero que esto sea de ayuda.


0

En tsql: Float, 0.0 almacena como 0 y no requiere definir después del dígito del punto decimal, por ejemplo, no necesita escribir Float (4,2). Decimal, 0.0 almacena como 0.0 y tiene la opción de definir como decimal (4,2), sugeriría 0.00-1.00, al hacer esto puede calcular el valor de ese porcentaje sin multiplicar por 100, y si informa, configure el tipo de datos de esa columna como porcentaje como MS Excel y otras vistas de plataforma 0.5 -> 50%.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.