Pregunta

Siempre digo en c # que una variable de tipo double no es adecuada para el dinero. Todas las cosas raras pueden suceder. Pero parece que no puedo crear un ejemplo para demostrar algunos de estos problemas. ¿Alguien puede dar ese ejemplo?

(editar; esta publicación se etiquetó originalmente como C #; algunas respuestas se refieren a detalles específicos de decimal , lo que significa System.Decimal ).

(edición 2: era específico pidiendo un código C #, así que no creo que esto sea solo independiente del lenguaje)

¿Fue útil?

Solución

Muy, muy inadecuado. Use decimal.

double x = 3.65, y = 0.05, z = 3.7;
Console.WriteLine((x + y) == z); // false

(ejemplo de la página de Jon aquí - lectura recomendada ;-p)

Otros consejos

Obtendrá errores impares causados ??efectivamente por el redondeo. Además, las comparaciones con valores exactos son extremadamente complicadas: por lo general, debe aplicar algún tipo de épsilon para verificar que el valor real esté "cerca". uno en particular.

Aquí hay un ejemplo concreto:

using System;

class Test
{
    static void Main()
    {
        double x = 0.1;
        double y = x + x + x;
        Console.WriteLine(y == 0.3); // Prints False
    }
}

Sí, no es adecuado.

Si recuerdo correctamente, el doble tiene alrededor de 17 números significativos, por lo que normalmente se producirán errores de redondeo muy por detrás del punto decimal. La mayoría del software financiero usa 4 decimales detrás del punto decimal, lo que deja 13 decimales para trabajar, por lo que el número máximo con el que puede trabajar para operaciones individuales sigue siendo mucho más alto que la deuda nacional de EE. UU. Pero los errores de redondeo se sumarán con el tiempo. Si su software funciona durante mucho tiempo, eventualmente comenzará a perder centavos. Ciertas operaciones empeorarán esto. Por ejemplo, agregar grandes cantidades a pequeñas cantidades provocará una pérdida significativa de precisión.

Necesita tipos de datos de punto fijo para operaciones de dinero, a la mayoría de las personas no les importa si pierde un centavo aquí y allá, pero los contadores no son como la mayoría de las personas ...

editar
De acuerdo con este sitio http://msdn.microsoft.com/en-us/library /678hzkk9.aspx Los dobles tienen de 15 a 16 dígitos significativos en lugar de 17.

@Jon Skeet decimal es más adecuado que el doble debido a su mayor precisión, 28 o 29 decimales significativos. Eso significa menos posibilidades de que los errores de redondeo acumulados se vuelvan significativos. Los tipos de datos de punto fijo (es decir, enteros que representan centavos o centésimas de centavo como he visto) como las menciones de Boojum son en realidad más adecuados.

Dado que decimal usa un factor de escala de múltiplos de 10, números como 0.1 se pueden representar exactamente. En esencia, el tipo decimal representa esto como 1/10 ^ 1, mientras que un double representaría esto como 104857/2 ^ 20 (en realidad sería más como número realmente grande / 2 ^ 1023).

Un decimal puede representar exactamente cualquier valor de base 10 con hasta 28/29 dígitos significativos (como 0.1). Un doble no puede.

Entiendo que la mayoría de los sistemas financieros expresan moneda usando números enteros, es decir, contando todo en centavos.

IEEE doble precisión en realidad puede representar todos los enteros exactamente en el rango de -2 ^ 53 a + 2 ^ 53. (Hacker's Delight, pág. 262) Si usa solo sumas, restas y multiplicaciones, y mantiene todo en enteros dentro de este rango, entonces no debería ver pérdida de precisión. Sin embargo, me preocuparía mucho la división u operaciones más complejas.

Usar el doble cuando no sabes lo que estás haciendo no es adecuado.

" doble " puede representar una cantidad de un billón de dólares con un error de 1/90 de centavo. Entonces obtendrá resultados muy precisos. ¿Quieres calcular cuánto cuesta poner a un hombre en Marte y recuperarlo con vida? doble hará bien.

Pero con el dinero a menudo hay reglas muy específicas que dicen que cierto cálculo debe dar un cierto resultado y no otro. Si calcula una cantidad que es muy muy muy cercana a $ 98.135, a menudo habrá una regla que determina si el resultado debe ser $ 98.14 o $ 98.13 y debe debe seguir esa regla y obtener el resultado requerido .

Dependiendo de dónde viva, usar enteros de 64 bits para representar centavos o centavos o kopeks o lo que sea la unidad más pequeña en su país generalmente funcionará bien. Por ejemplo, los enteros con signo de 64 bits que representan centavos pueden representar valores de hasta 92,223 billones de dólares. Los enteros de 32 bits generalmente no son adecuados.

No un doble siempre tendrá errores de redondeo, use " decimal " si estás en .Net ...

En realidad, la coma flotante doble es perfectamente adecuada para representar cantidades de dinero siempre que elija una unidad adecuada.

Ver http://www.idinews.com/moneyRep.html

Entonces, el punto fijo es largo . O consume 8 bytes, seguramente preferible a los 16 consumidos por un elemento decimal .

Si algo funciona o no (es decir, produce el resultado esperado y correcto) no es cuestión de votación ni de preferencia individual. Una técnica funciona o no.

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