.net - entre - tipos de datos float double




¿Diferencia entre decimal, float y doble en.NET? (11)

¿Cuál es la diferencia entre decimal , float y double en .NET?

¿Cuándo alguien usaría uno de estos?


  1. Double y float se pueden dividir por entero cero sin excepción en el tiempo de compilación y ejecución.
  2. El decimal no se puede dividir por entero cero. La compilación siempre fallará si haces eso.

El problema con todos estos tipos es que subsiste 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 TRUE!

Si sustituyo Doble por decimal, bLower contiene FALSO, que es la buena respuesta.

En doble, el problema es que fMean-fDelta = 1.09999999999 que es inferior a 1.1.

Precaución: creo que el mismo problema 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 a BINARY decimal 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) 

Este ha sido un tema interesante para mí, ya que hoy hemos tenido un pequeño error desagradable, en relación con el decimal tiene menos precisión que un float .

En nuestro código C #, estamos leyendo valores numéricos de una hoja de cálculo de Excel, los convertimos en un decimal y luego enviamos este decimal a un Servicio para guardarlo 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ó a la perfección. Pero para algunos, los valores de Excel muy pequeños, utilizando decimal.TryParse perdieron el valor completamente. Un ejemplo de ello es

  • Valor de celda = 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;
    …
}

Aunque el double tiene menos precisión que un decimal , esto en realidad aseguró que los pequeños números aún serían reconocidos. Por alguna razón, double.TryParse fue capaz de recuperar números tan pequeños, mientras que decimal.TryParse pondría a cero.

Impar. Muy raro.


La estructura decimal está estrictamente orientada a los 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:

  • Una cierta pérdida de precisión es aceptable en muchos cálculos científicos debido a los límites prácticos del problema físico o el artefacto que se mide. La pérdida de precisión no es aceptable en las finanzas.
  • El decimal es mucho (mucho) más lento que el flotante y el doble para la mayoría de las operaciones, principalmente porque las operaciones de punto flotante se realizan en binario, mientras que el decimal se realiza en la base 10 (es decir, el hardware de la FPU maneja los flotantes y los dobles, como MMX / SSE). , mientras que los decimales se calculan en software).
  • El decimal tiene un rango de valores inaceptablemente más pequeño que el doble, a pesar del hecho de que admite más dígitos de precisión. Por lo tanto, Decimal no se puede utilizar para representar muchos valores científicos.

La principal diferencia entre cada uno de estos es la precisión.

float es un número de 32-bit , double es un número de 64-bit y decimal es un número de 128-bit .


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. Puedes usar el tipo doble o el tipo flotante. Configure estos tipos de variables exactamente de la misma manera: en lugar de usar la palabra int , escriba double o float . Me gusta esto:

float myFloat;
double myDouble;

( float es corto para "punto flotante", y solo significa un número con un punto algo en el extremo).

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 el 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 el botón doble. El cuadro de mensaje muestra correctamente el número. Sin embargo, agregue otro número al final, y C # se redondeará nuevamente hacia arriba o hacia abajo. La moraleja es que si quieres precisión, ¡cuidado con el redondeo!


Nadie ha mencionado eso

En la configuración predeterminada, Flotantes (System.Single) y 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;

No reiteraré toneladas de información buena (y mala) ya respondida en otras respuestas y comentarios, pero responderé a su pregunta de seguimiento con una sugerencia:

¿Cuándo alguien usaría uno de estos?

Usar decimal para valores contados

Use float / double para los 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. Normalmente medimos la distancia. A menudo contamos puntuaciones.

* En algunos casos, lo que yo llamaría distancia nominal , es posible que queramos "contar" la distancia. Por ejemplo, tal vez estamos tratando con signos de países que muestran distancias a ciudades, y sabemos que esas distancias nunca tienen más de un dígito decimal (xxx.x km).


flotador ~ ± 1.5 x 10-45 a ± 3.4 x 1038 -------- 7 figuras
doble ~ ± 5.0 x 10-324 a ± 1.7 x 10308 ------ 15 o 16 figuras
decimal ~ ± 1.0 x 10-28 a ± 7.9 x 1028 -------- 28 o 29 cifras


float 7 digitos de precision

double tiene unos 15 dígitos de precisión.

decimal tiene alrededor de 28 dígitos de precisión

Si necesita mayor precisión, use doble en lugar de flotador. En las CPU modernas, ambos tipos de datos tienen casi el mismo rendimiento. El único beneficio de usar el flotador es que ocupan menos espacio. Prácticamente importa solo si tienes muchos de ellos.

He encontrado que esto es interesante. Lo que todo científico informático debe saber sobre la aritmética de punto flotante


+---------+----------------+---------+----------+---------------------------------------------+
| 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                               |
+---------+----------------+---------+----------+---------------------------------------------+

Para más información, ver:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/921a8ffc-9829-4145-bdc9-a96c1ec174a5





decimal