¿Qué es la diferencia entre decimal
, float
y double
en .NET?
¿Cuándo alguien usaría uno de estos?
¿Qué es la diferencia entre decimal
, float
y double
en .NET?
¿Cuándo alguien usaría uno de estos?
Respuestas:
float
y double
son tipos de punto binario flotante . En otras palabras, representan un número como este:
10001.10010110011
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:
12345.65789
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.
float
/ double
generalmente no representan números como 101.101110
, normalmente se representa como algo así como 1101010 * 2^(01010010)
un exponente
float
es una palabra clave de alias C # y no es un tipo .Net. susSystem.Single
... single
y double
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.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Resultado:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
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
y 0.1 + 1e-8
, mientras decimal
se fusionará 0.1
y 0.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 hace 0.1
"mejor" 0.10000001
es que a los seres humanos les gusta la base 10. E incluso con un float
valor, si inicializas dos valores de 0.1
la misma manera, ambos serán el mismo valor . Es solo que ese valor no será exactamente 0.1
, será el valor más cercano al 0.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;
entonces a == b
será cierto . Es solo eso a
y ambos no b
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:
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
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:
¿Cuándo alguien usaría uno de estos?
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).
float
7 dígitos de precisión
double
tiene unos 15 dígitos de precisión
decimal
tiene unos 28 dígitos de precisión
Si 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
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, y double
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 contabilidad Real
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, usar double
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
En la configuración predeterminada, los flotantes (System.Single) y los dobles (System.Double) nunca usarán la verificación de desbordamiento, mientras que Decimal (System.Decimal) siempre usará la verificación de desbordamiento.
quiero decir
decimal myNumber = decimal.MaxValue;
myNumber += 1;
lanza OverflowException .
Pero estos no:
float myNumber = float.MaxValue;
myNumber += 1;
Y
double myNumber = double.MaxValue;
myNumber += 1;
float.MaxValue+1 == float.MaxValue
, igual que decimal.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.
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
, escribe double
o float
. Me gusta esto:
float myFloat;
double myDouble;
( 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. Para double
s, puede tener hasta 16 dígitos. Para ser más precisos, aquí está el tamaño oficial:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
es un número de 32 bits y double
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:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Detenga su programa y regrese a la ventana de codificación. Cambia esta línea:
myDouble = 0.007;
myDouble = 12345678.1234567;
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!
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 a float
.
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 de decimal
vuelta a un Servicio para guardarlos en una base de datos de SQL Server .
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
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 es
cellValue = 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 un decimal
:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
A pesar de que double
tiene menos precisión que a decimal
, 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, mientras decimal.TryParse
que los puso a cero.
Impar. Muy raro.
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!
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
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
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
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
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
En palabras simples:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Puedes leer más aquí , Flotante , Doble y Decimal .
Decimal
adecuado para aplicaciones financieras, y es el criterio principal a utilizar al decidir entre Decimal
y Double
. Es raro que la Double
precisión no sea suficiente para aplicaciones científicas, por ejemplo (y a Decimal
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 un 32-bit
número, double
es un 64-bit
número y decimal
es un 128-bit
número.
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 un double/float
.
Decimals
y Floats/Doubles
no se puede comparar sin un yeso mientras que Floats
yDoubles
puede.
Decimals
también permite la codificación o ceros finales.
debe mencionar valores como:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
y verifica los resultados.
Float - 4
Double - 8
Decimal - 12