¿Qué es la diferencia entre decimal
, float
y double
en .NET?
¿Cuándo alguien usaría uno de estos?
.net
floating-point
double
decimal
PC Luddite
fuente
fuente
Respuestas:
float
ydouble
son tipos de punto binario flotante . En otras palabras, representan un número como este:El número binario y la ubicación del punto binario están codificados dentro del valor.
decimal
es un flotante decimal tipo de punto . En otras palabras, representan un número como este:Nuevamente, el número y la ubicación del punto decimal están codificados dentro del valor; eso es lo que hace que sea
decimal
un tipo de punto flotante en lugar de un tipo de punto fijo.Lo importante a tener en cuenta es que los humanos están acostumbrados a representar no enteros en forma decimal, y esperan resultados exactos en representaciones decimales; no todos los números decimales son exactamente representables en coma flotante binaria - 0.1, por ejemplo - así que si usa un valor de coma flotante binaria, obtendrá una aproximación de 0.1. También obtendrá aproximaciones cuando utilice un punto decimal flotante; por ejemplo, el resultado de dividir 1 por 3 no puede representarse exactamente.
En cuanto a qué usar cuando:
Para valores que son "decimales exactos de forma natural" es bueno usarlo
decimal
. Esto suele ser adecuado para cualquier concepto inventado por los humanos: los valores financieros son el ejemplo más obvio, pero también hay otros. Considere la puntuación dada a los buceadores o patinadores sobre hielo, por ejemplo.Para valores que son más objetos de la naturaleza que en realidad no puede medirse con exactitud todos modos,
float
/double
son más apropiados. Por ejemplo, los datos científicos generalmente se representarían de esta forma. Aquí, los valores originales no serán "decimalmente precisos" para comenzar, por lo que no es importante que los resultados esperados mantengan la "precisión decimal". Los tipos de punto binario flotante son mucho más rápidos para trabajar que los decimales.fuente
float
/double
generalmente no representan números como101.101110
, normalmente se representa como algo así como1101010 * 2^(01010010)
un exponentefloat
es una palabra clave de alias C # y no es un tipo .Net. susSystem.Single
...single
ydouble
son tipos de punto binario flotante.La precisión es la principal diferencia.
Flotador : 7 dígitos (32 bits)
Doble -15-16 dígitos (64 bits)
Decimal -28-29 dígitos significativos (128 bits)
Los decimales tienen una precisión mucho mayor y generalmente se usan en aplicaciones financieras que requieren un alto grado de precisión. Los decimales son mucho más lentos (hasta 20 veces más en algunas pruebas) que un doble / flotante.
Los decimales y los flotadores / dobles no se pueden comparar sin un yeso, mientras que los flotadores y los dobles sí. Los decimales también permiten la codificación o ceros finales.
Resultado:
fuente
0.1
, ¡eso rara vez es el caso en el mundo real! Cualquier formato de almacenamiento finito combinará un número infinito de valores posibles con un número finito de patrones de bits. Por ejemplo,float
se fusionará0.1
y0.1 + 1e-8
, mientrasdecimal
se fusionará0.1
y0.1 + 1e-29
. Claro, dentro de un rango dado , ciertos valores pueden representarse en cualquier formato con cero pérdida de precisión (por ejemplo,float
puede almacenar cualquier número entero de hasta 1.6e7 con cero pérdida de precisión), pero eso no es una precisión infinita .0.1
es un valor especial ! Lo único que lo hace0.1
"mejor"0.10000001
es que a los seres humanos les gusta la base 10. E incluso con unfloat
valor, si inicializas dos valores de0.1
la misma manera, ambos serán el mismo valor . Es solo que ese valor no será exactamente0.1
, será el valor más cercano al0.1
que se puede representar exactamente como afloat
. Claro, con flotantes binarios(1.0 / 10) * 10 != 1.0
, pero con flotantes decimales,(1.0 / 3) * 3 != 1.0
tampoco. Ninguno de los dos es perfectamente preciso.double a = 0.1; double b = 0.1;
entoncesa == b
será cierto . Es solo esoa
y ambos nob
serán exactamente iguales . En C #, si lo hace entonces también será cierto. Pero en ese caso, ni de ni hará exactamente igual - igual que lo harán tanto . En ambos casos, se pierde algo de precisión debido a la representación. Usted tercamente dice que tiene una precisión "infinita", que es falsa .0.1
decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
a == b
a
b
1/3
0.3333...
decimal
La estructura decimal está estrictamente orientada a cálculos financieros que requieren precisión, que son relativamente intolerantes al redondeo. Los decimales no son adecuados para aplicaciones científicas, sin embargo, por varias razones:
fuente
Ver aquí para más información .
fuente
No reiteraré toneladas de buena (y alguna mala) información ya respondida en otras respuestas y comentarios, pero responderé su pregunta de seguimiento con un consejo:
Usar decimal para valores contados
Use flotante / doble para valores medidos
Algunos ejemplos:
dinero (¿contamos dinero o medimos dinero?)
distancia (¿contamos la distancia o medimos la distancia? *)
puntajes (¿contamos puntajes o medimos puntajes?)
Siempre contamos el dinero y nunca debemos medirlo. Usualmente medimos la distancia. A menudo contamos los puntajes.
* En algunos casos, lo que yo llamaría distancia nominal , es posible que deseemos 'contar' la distancia. Por ejemplo, tal vez estamos tratando con signos de país que muestran distancias a ciudades, y sabemos que esas distancias nunca tienen más de un dígito decimal (xxx.x km).
fuente
float
7 dígitos de precisióndouble
tiene unos 15 dígitos de precisióndecimal
tiene unos 28 dígitos de precisiónSi necesita una mayor precisión, use doble en lugar de flotante. En las CPU modernas, ambos tipos de datos tienen casi el mismo rendimiento. El único beneficio de usar flotador es que ocupan menos espacio. Prácticamente solo importa si tienes muchos de ellos.
Encontré que esto es interesante. Lo que todo informático debe saber sobre la aritmética de coma flotante
fuente
double
apropiado en aplicaciones de contabilidad en aquellos casos (y básicamente solo en aquellos casos) en los que no estaba disponible ningún tipo de entero mayor de 32 bits, ydouble
se estaba utilizando como si fuera un tipo de entero de 53 bits (por ejemplo, para mantener un número entero de centavos, o un número entero de centésimas de centavo). Hoy en día no se usa mucho para tales cosas, pero muchos lenguajes obtuvieron la capacidad de usar valores de punto flotante de doble precisión mucho antes de que obtuvieran matemáticas enteras de 64 bits (¡o en algunos casos incluso de 32 bits!).Real
IIRC podría representar valores de hasta 1.8E + 19 con precisión de unidad. Creo que sería mucho más sensato usar una aplicación de contabilidadReal
para representar un número entero de centavos que ...double
tipo que tenga una precisión de unidad de hasta 9E15. Si uno necesita almacenar números enteros que son más grandes que el tipo entero más grande disponible, usardouble
es más simple y más eficiente que tratar de evitar las matemáticas de precisión múltiple, especialmente dado que los procesadores tienen instrucciones para realizar 16x16-> 32 o. ..Nadie ha mencionado eso
quiero decir
lanza OverflowException .
Pero estos no:
Y
fuente
float.MaxValue+1 == float.MaxValue
, igual quedecimal.MaxValue+0.1D == decimal.MaxValue
. ¿Quizás quisiste decir algo asífloat.MaxValue*2
?System.Decimal
lanza una excepción justo antes de que se vuelve incapaz de distinguir unidades enteras, pero si se supone una aplicación que se trata de dólares y centavos, por ejemplo, que podría ser demasiado tarde.fuente
decimal
por cero (CS0020), y lo mismo ocurre con los literales integrales. Sin embargo, si un valor decimal en tiempo de ejecución se divide por cero, obtendrá una excepción, no un error de compilación.Los enteros, como se mencionó, son números enteros. No pueden almacenar el punto algo, como .7, .42 y .007. Si necesita almacenar números que no son números enteros, necesita un tipo diferente de variable. Puede usar el tipo doble o el tipo flotante. Configura estos tipos de variables exactamente de la misma manera: en lugar de usar la palabra
int
, escribedouble
ofloat
. Me gusta esto:(
float
es la abreviatura de "punto flotante", y solo significa un número con un punto algo al final).La diferencia entre los dos está en el tamaño de los números que pueden contener. Para
float
, puede tener hasta 7 dígitos en su número. Paradouble
s, puede tener hasta 16 dígitos. Para ser más precisos, aquí está el tamaño oficial:float
es un número de 32 bits ydouble
es un número de 64 bits.Haga doble clic en su nuevo botón para obtener el código. Agregue las siguientes tres líneas a su código de botón:
Detenga su programa y regrese a la ventana de codificación. Cambia esta línea:
Ejecute su programa y haga clic en su botón doble. El cuadro de mensaje muestra correctamente el número. Sin embargo, agregue otro número al final y C # nuevamente se redondeará hacia arriba o hacia abajo. La moraleja es que si quieres precisión, ¡ten cuidado de redondear!
fuente
fuente
decimal
realidad se almacena en formato decimal (a diferencia de la base 2; por lo que no perderá ni redondeará los dígitos debido a la conversión entre los dos sistemas numéricos); Además,decimal
no tiene ningún concepto de valores especiales como NaN, -0, ∞ o -∞.Este ha sido un hilo interesante para mí, ya que hoy, hemos tenido un pequeño error desagradable, con respecto a
decimal
tener menos precisión que afloat
.En nuestro código C #, leemos valores numéricos de una hoja de cálculo de Excel, los convertimos en a
decimal
y luego los enviamos dedecimal
vuelta a un Servicio para guardarlos en una base de datos de SQL Server .Ahora, para casi todos nuestros valores de Excel, esto funcionó maravillosamente. Pero para algunos valores de Excel muy pequeños, el uso
decimal.TryParse
perdió el valor por completo. Uno de esos ejemplos escellValue = 0.00006317592
Decimal. TryParse (cellValue.ToString (), valor de salida); // devolvería 0
La solución, extrañamente, fue convertir los valores de Excel en un
double
primero, y luego en undecimal
:A pesar de que
double
tiene menos precisión que adecimal
, esto realmente aseguró que aún se reconocerían números pequeños. Por alguna razón,double.TryParse
fue capaz de recuperar números tan pequeños, mientrasdecimal.TryParse
que los puso a cero.Impar. Muy raro.
fuente
decimal.Parse("0.00006317592")
funciona, tienes algo más que hacer. - Posiblemente notación científica?Para aplicaciones como juegos y sistemas embebidos donde la memoria y el rendimiento son críticos, el flotante suele ser el tipo numérico de elección, ya que es más rápido y la mitad del tamaño de un doble. Los enteros solían ser el arma preferida, pero el rendimiento de coma flotante ha superado a los enteros en los procesadores modernos. ¡Decimal ya está listo!
fuente
Los tipos de variable Decimal, Double y Float son diferentes en la forma en que almacenan los valores. La precisión es la principal diferencia donde flotante es un tipo de datos de coma flotante de precisión simple (32 bits), el doble es un tipo de datos de coma flotante de doble precisión (64 bits) y el decimal es un tipo de datos de coma flotante de 128 bits.
Flotador: 32 bits (7 dígitos)
Doble - 64 bit (15-16 dígitos)
Decimal: 128 bits (28-29 dígitos significativos)
Más sobre ... la diferencia entre Decimal, Float y Double
fuente
El problema con todos estos tipos es que subsiste una cierta imprecisión Y que este problema puede ocurrir con números decimales pequeños como en el siguiente ejemplo
Pregunta: ¿Qué valor contiene la variable bLower?
Respuesta: ¡En una máquina de 32 bits, bLower contiene VERDADERO!
Si reemplazo Double por Decimal, bLower contiene FALSE, que es la buena respuesta.
En doble, el problema es que fMean-fDelta = 1.09999999999 que es menor que 1.1.
Precaución: Creo que el mismo problema ciertamente puede existir para otro número porque Decimal es solo un doble con mayor precisión y la precisión siempre tiene un límite.
De hecho, ¡Double, Float y Decimal corresponden al decimal BINARIO en COBOL!
Es lamentable que otros tipos numéricos implementados en COBOL no existan en .Net. Para aquellos que no conocen COBOL, existen en COBOL después del tipo numérico
fuente
En palabras simples:
fuente
Decimal
adecuado para aplicaciones financieras, y es el criterio principal a utilizar al decidir entreDecimal
yDouble
. Es raro que laDouble
precisión no sea suficiente para aplicaciones científicas, por ejemplo (y aDecimal
menudo no es adecuada para aplicaciones científicas debido a su alcance limitado).La principal diferencia entre cada uno de estos es la precisión.
float
es un32-bit
número,double
es un64-bit
número ydecimal
es un128-bit
número.fuente
Decimal de 128 bits (28-29 dígitos significativos) En el caso de aplicaciones financieras, es mejor usar tipos decimales porque le brinda un alto nivel de precisión y es fácil evitar errores de redondeo. Use decimal para cálculos no enteros donde se necesita precisión (p. Ej. dinero y moneda)
Doble tipo de 64 bits (15-16 dígitos) Los tipos dobles son probablemente el tipo de datos más utilizado para valores reales, excepto el manejo de dinero. Use el doble para las matemáticas no enteras donde la respuesta más precisa no es necesaria.
Flotante de 32 bits (7 dígitos) 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.
Decimals
son mucho más lentos que undouble/float
.Decimals
yFloats/Doubles
no se puede comparar sin un yeso mientras queFloats
yDoubles
puede.Decimals
también permite la codificación o ceros finales.fuente
Para definir decimal, flotante y doble en .Net (c #)
debe mencionar valores como:
y verifica los resultados.
Y los bytes ocupados por cada uno son
fuente