Pregunta

Puedo nombrar tres ventajas de usar doble (o float ) en lugar de decimal :

  1. Utiliza menos memoria.
  2. Más rápido porque las operaciones matemáticas de punto flotante son compatibles de forma nativa con los procesadores.
  3. Puede representar un mayor rango de números.

Pero estas ventajas parecen aplicarse solo a las operaciones de cálculo intensivo, como las que se encuentran en el software de modelado. Por supuesto, los dobles no se deben usar cuando se requiere precisión, como los cálculos financieros. Entonces, ¿existen razones prácticas para elegir double (o float ) en lugar de decimal en " normal " aplicaciones?

Editado para agregar: Gracias por todas las excelentes respuestas, aprendí de ellas.

Otra pregunta: algunas personas señalaron que los dobles pueden representar con mayor precisión los números reales. Cuando se declara, creo que normalmente también los representan con mayor precisión. ¿Pero es una afirmación verdadera de que la precisión puede disminuir (a veces significativamente) cuando se realizan operaciones de punto flotante?

¿Fue útil?

Solución

Creo que has resumido las ventajas bastante bien. Sin embargo, te estás perdiendo un punto. El tipo decimal es solo más Exactos al representar los números base 10 (p. ej., los utilizados en los cálculos de moneda / financieros). En general, el tipo double ofrecerá al menos la mayor precisión (alguien me corrige si me equivoco) y, definitivamente, una mayor velocidad para números reales arbitrarios. La conclusión simple es: cuando considere cuál usar, use siempre doble a menos que necesite la precisión de base 10 que ofrece decimal .

Editar:

Con respecto a su pregunta adicional sobre la disminución en la precisión de los números de punto flotante después de las operaciones, este es un problema ligeramente más sutil. De hecho, la precisión (yo uso el término indistintamente para la precisión aquí) disminuirá constantemente después de que se realice cada operación. Esto se debe a dos razones:

  1. el hecho de que ciertos números (la mayoría de los decimales, obviamente) no pueden representarse verdaderamente en forma de punto flotante
  2. se producen errores de redondeo, como si estuviera haciendo el cálculo a mano. Sin embargo, depende en gran medida del contexto (cuántas operaciones esté realizando) si estos errores son lo suficientemente significativos como para justificar su reflexión.

En todos los casos, si desea comparar dos números de punto flotante que en teoría deberían ser equivalentes (pero se llegó a usar diferentes cálculos), debe permitir un cierto grado de tolerancia (cuánto varía, pero generalmente es muy pequeño).

Para obtener una descripción más detallada de los casos particulares en los que se pueden introducir errores en las precisiones, consulte la sección Precisión de artículo de Wikipedia . Finalmente, si desea una discusión seriamente profunda (y matemática) de los números / operaciones de punto flotante a nivel de máquina, intente leer el artículo a menudo citado Lo que todo científico informático debe saber sobre la aritmética de punto flotante .

Otros consejos

Pareces acertado con los beneficios de usar un tipo de punto flotante. Tiendo a diseñar decimales en todos los casos, y confío en un generador de perfiles para avisarme si las operaciones en decimal están causando cuellos de botella o retrasos. En esos casos, voy a "echar abajo" para duplicar o flotar, pero solo hágalo internamente, y trate de manejar con cuidado la pérdida de precisión limitando el número de dígitos significativos en la operación matemática que se realiza.

En general, si su valor es transitorio (no se reutiliza), es seguro usar un tipo de punto flotante. El problema real con los tipos de punto flotante son los siguientes tres escenarios.

  1. Está agregando valores de punto flotante (en cuyo caso, los errores de precisión están compuestos)
  2. Construye valores basados ??en el valor de punto flotante (por ejemplo, en un algoritmo recursivo)
  3. Estás haciendo matemáticas con un número muy amplio de dígitos significativos (por ejemplo, 123456789.1 * .0000000000000987654321 )

EDIT

De acuerdo con la documentación de referencia sobre decimales de C # :

  

La palabra clave decimal denota un   Tipo de datos de 128 bits. Comparado con   tipos de punto flotante, el tipo decimal   Tiene una mayor precisión y una menor.   gama, lo que lo hace adecuado para   cálculos financieros y monetarios.

Para aclarar mi declaración anterior:

  

Tiendo a diseñar decimales en todos   casos, y confiar en un perfilador para dejar   yo sé si las operaciones en decimal es   causando cuellos de botella o ralentizaciones.

Solo he trabajado en industrias donde los decimales son favorables. Si está trabajando en motores físicos o gráficos, probablemente sea mucho más beneficioso diseñar para un tipo de punto flotante (flotante o doble).

El decimal no es infinitamente preciso (es imposible representar una precisión infinita para no integral en un tipo de datos primitivo), pero es mucho más preciso que el doble:

  • decimal = 28-29 dígitos significativos
  • doble = 15-16 dígitos significativos
  • float = 7 dígitos significativos

EDIT 2

En respuesta al comentario de Konrad Rudolph , el artículo # 1 (arriba) es definitivamente correcto. La agregación de la imprecisión de hecho se complica. Vea el siguiente código para ver un ejemplo:

private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;

public static void Main(string[] args)
{
    Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
    float asSingle = 0f;
    double asDouble = 0d;
    decimal asDecimal = 0M;

    for (int i = 0; i < ONE_MILLION; i++)
    {
        asSingle += THREE_FIFTHS;
        asDouble += THREE_FIFTHS;
        asDecimal += (decimal) THREE_FIFTHS;
    }
    Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
    Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
    Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
    Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
    Console.ReadLine();
}

Esto produce lo siguiente:

Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000

Como puede ver, aunque estamos agregando desde la misma constante de origen, los resultados del doble son menos precisos (aunque probablemente se redondearán correctamente), y el flotador es mucho menos preciso, hasta el punto en el que ha sido reducido a solo dos dígitos significativos.

Usa el decimal para los valores de base 10, por ejemplo, cálculos financieros, como otros han sugerido.

Pero el doble es generalmente más preciso para valores calculados arbitrarios.

Por ejemplo, si desea calcular el peso de cada línea en una cartera, use el doble ya que el resultado se agregará más al 100%.

En el siguiente ejemplo, doubleResult está más cerca de 1 que decimalResult:

// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;

Tomando nuevamente el ejemplo de una cartera:

  • El valor de mercado de cada línea de la cartera es un valor monetario y probablemente se represente mejor como decimal.

  • El peso de cada línea en la cartera (= Valor de mercado / SUM (Valor de mercado)) generalmente se representa mejor como doble.

Use un doble o un flotador cuando no necesite precisión, por ejemplo, en un juego de plataformas que escribí, usé un flotador para almacenar las velocidades del jugador. Obviamente, no necesito una súper precisión aquí porque eventualmente redondeo a un Int para dibujar en la pantalla.

En algunas cuentas, considere la posibilidad de usar tipos integrales en lugar o en conjunto. Por ejemplo, digamos que las reglas bajo las cuales opera requieren que cada resultado de cálculo se lleve a cabo con al menos 6 posiciones decimales y el resultado final se redondeará al centavo más cercano.

Un cálculo de 1/6 de $ 100 produce $ 16.66666666666666 ..., por lo que el valor que se lleva a cabo en una hoja de cálculo será de $ 16.666667. Tanto el doble como el decimal deberían dar ese resultado con precisión a 6 lugares decimales. Sin embargo, podemos evitar cualquier error acumulativo llevando el resultado hacia adelante como un número entero 16666667. Cada cálculo posterior se puede hacer con la misma precisión y se puede llevar de manera similar. Continuando con el ejemplo, calculo el impuesto a las ventas de Texas sobre esa cantidad (16666667 * .0825 = 1375000). Sumando los dos (es una hoja de cálculo corta) 1666667 + 1375000 = 18041667. Mover el punto decimal hacia atrás nos da 18.041667, o $ 18.04.

Si bien este breve ejemplo no generaría un error acumulativo al usar doble o decimal, es bastante fácil mostrar casos en los que simplemente calcular el doble o decimal y seguir adelante acumularía un error significativo. Si las reglas bajo las cuales opera requieren un número limitado de lugares decimales, almacene cada valor como un entero multiplicando por 10 ^ (número requerido de lugar decimal), y luego dividiendo por 10 ^ (número requerido de lugares decimales) para obtener el valor real El valor evitará cualquier error acumulativo.

En situaciones donde no se producen fracciones de centavos (por ejemplo, una máquina expendedora), no hay ninguna razón para usar tipos no integrales. Simplemente piense en ello como contar centavos, no dólares. He visto un código en el que cada cálculo involucraba solo centavos enteros, ¡pero el uso del doble condujo a errores! Integer sólo las matemáticas eliminaron el problema. Así que mi respuesta poco convencional es, cuando sea posible, renunciar al doble y al decimal.

Si necesita interrumpir binario con otros lenguajes o plataformas, es posible que deba usar float o double, que están estandarizados.

Nota: esta publicación está basada en la información de las capacidades del tipo decimal de http: // csharpindepth. com / Articles / General / Decimal.aspx y mi propia interpretación de lo que eso significa. Asumiré que Doble es la precisión doble IEEE normal.

Nota2: el más pequeño y el más grande en esta publicación se refiere a la magnitud del número.

Ventajas de " decimal " ;.

  • " decimal " puede representar números exactos que pueden escribirse como fracciones decimales (suficientemente cortas), el doble no puede. Esto es importante en los libros de contabilidad financiera y es similar, donde es importante que los resultados coincidan exactamente con lo que daría un humano haciendo los cálculos.
  • " decimal " tiene una mantisa mucho más grande que " double " Eso significa que para los valores dentro de su rango normalizado " decimal " Tendrá una precisión mucho mayor que el doble.

Contras de decimal

  • Será mucho más lento (no tengo puntos de referencia, pero supongo que al menos un orden de magnitud tal vez más), el decimal no se beneficiará de ninguna aceleración de hardware y la aritmética requerirá una multiplicación / división por costos relativamente alta de 10 (que es mucho más costoso que la multiplicación y la división por potencias de 2) para igualar el exponente antes de la suma / resta y para devolver el exponente al rango después de la multiplicación / división.
  • el decimal se desbordará antes que el doble de voluntad. decimal solo puede representar números hasta & # 177; 2 96 -1. Por comparación, el doble puede representar números hasta casi & # 177; 2 1024
  • decimal se desbordará antes. Los números más pequeños que se pueden representar en decimal son & # 177; 10 -28 . Por comparación, el doble puede representar valores hasta 2 -149 (aprox. 10 -45 ) si se admiten números subnromales y 2 -126 (aprox. 10 -38 ) si no lo son.
  • el decimal ocupa el doble de memoria que el doble.

Mi opinión es que deberías usar de forma predeterminada " decimal " para el trabajo con dinero y otros casos en los que el cálculo de la concordancia humana es importante y que debe usar el doble como su elección predeterminada el resto del tiempo.

Use puntos flotantes si valora el rendimiento por encima de la corrección.

Elija el tipo en función de su aplicación. Si necesita precisión como en el análisis financiero, ha respondido a su pregunta. Pero si su aplicación puede llegar a un acuerdo con una estimación de su aprobación con el doble.

¿Su aplicación necesita un cálculo rápido o tendrá todo el tiempo del mundo para darle una respuesta? Realmente depende del tipo de aplicación.

¿Gráfico hambriento? flotar o doble es suficiente. ¿Análisis de datos financieros, meteoro golpeando un planeta de precisión? Esos necesitarían un poco de precisión :)

El decimal tiene bytes más anchos, el doble es soportado de forma nativa por la CPU. El decimal es base-10, por lo que se produce una conversión de decimal a doble mientras se calcula un decimal.

For accounting - decimal
For finance - double
For heavy computation - double

Tenga en cuenta que .NET CLR solo admite Math.Pow (doble, doble). Decimal no es compatible.

.NET Framework 4

[SecuritySafeCritical]
public static extern double Pow(double x, double y);

Los valores dobles se serializarán a notación científica de forma predeterminada si esa notación es más corta que la visualización decimal. (por ejemplo, .00000003 será 3e-8) Los valores decimales nunca se serializarán a notación científica. Al serializar para el consumo por un tercero, esto puede ser una consideración.

Depende de para qué lo necesites.

Debido a que flotante y doble son tipos de datos binarios, tiene some diifculties y errrors en la forma en números de rondas, por ejemplo, double redondearía 0.1 a 0.100000001490116, double would también ronda 1/3 a 0.33333334326441. En pocas palabras, no todos los números reales tienen una representación precisa en tipos dobles

Por suerte, C # también admite la llamada aritmética de coma flotante decimal, donde los números se representan mediante el sistema numérico decimal en lugar del sistema binario. Por lo tanto, la coma-aritmética de punto flotante decimal no pierde precisión al almacenar y procesar números de punto flotante. Esto hace que sea inmensamente adecuado para cálculos donde se necesita un alto nivel de precisión.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top