¿Cuál es el mejor tipo de datos para usar con dinero en C #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
¿Cuál es el mejor tipo de datos para usar con dinero en C #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
Respuestas:
Como se describe en decimal como:
La palabra clave decimal indica un tipo de datos de 128 bits. En comparación con los tipos de coma flotante, el tipo decimal tiene más precisión y un rango más pequeño, lo que lo hace apropiado para cálculos financieros y monetarios .
Puede usar un decimal de la siguiente manera:
decimal myMoney = 300.5m;
El tipo de valor decimal representa números decimales que van desde 79,228,162,514,264,337,593,543,950,335 positivos hasta 79,228,162,514,264,337,593,543,950,335 negativos. El tipo de valor decimal es apropiado para cálculos financieros que requieren grandes cantidades de dígitos integrales y fraccionarios significativos y sin errores de redondeo. El tipo decimal no elimina la necesidad de redondeo. Más bien, minimiza los errores debidos al redondeo.
Me gustaría señalar esta excelente respuesta de zneak sobre por qué el doble no debe usarse.
Utilice el patrón Money de Patrones de arquitectura de aplicaciones empresariales ; especifique la cantidad como decimal y la moneda como una enumeración.
Money
nuget tiene un enlace github muerto para el sitio del proyecto, así que ... ¿no hay documentos?
Decimal. Si elige el doble, se deja abierto a errores de redondeo
double
puede introducir errores de redondeo porque el punto flotante no puede representar todos los números exactamente (por ejemplo, 0.01 no tiene representación exacta en punto flotante). Decimal
, Por otro lado, no representar números con exactitud . (La compensación Decimal
tiene un rango menor que el punto flotante) El punto flotante puede generar * errores de redondeo * inadvertidos * (p 0.01+0.01 != 0.02
. Ej .). Decimal
puede darle errores de redondeo, pero solo cuando lo solicitó (por ejemplo, Math.Round(0.01+0.02)
devuelve cero)
double
y aplica cuidadosamente el escalado y el redondeo específico del dominio cuando sea apropiado, puede ser perfectamente preciso. Si uno es descuidado en el redondeo, decimal
puede producir resultados semánticamente incorrectos (por ejemplo, si se suman varios valores que se supone que se redondean al centavo más cercano, pero en realidad no los rodea primero). Lo único bueno decimal
es que la escala está integrada.
decimal tiene un rango más pequeño, pero una mayor precisión, ¡para que no pierdas todos esos centavos con el tiempo!
Detalles completos aquí:
De acuerdo con el patrón de dinero: el manejo de monedas es demasiado engorroso cuando usa decimales.
Si crea una clase de Moneda, puede colocar allí toda la lógica relacionada con el dinero, incluido un método ToString () correcto, un mayor control de los valores de análisis y un mejor control de las divisiones.
Además, con una clase de moneda, no hay posibilidad de mezclar dinero involuntariamente con otros datos.
Otra opción (especialmente si está rodando su propia clase) es usar un int o un int64, y designar los cuatro dígitos inferiores (o posiblemente incluso 2) como "a la derecha del punto decimal". Así que "en los bordes" necesitarás "* 10000" al entrar y "/ 10000" al salir. Este es el mecanismo de almacenamiento utilizado por el servidor SQL de Microsoft, consulte http://msdn.microsoft.com/en-au/library/ms179882.aspx
Lo bueno de esto es que toda su suma se puede hacer usando aritmética de enteros (rápidos).
La mayoría de las aplicaciones con las que he trabajado utilizan decimal
para representar dinero. Esto se basa en el supuesto de que la aplicación nunca tendrá que ver con más de una moneda.
Esta suposición puede basarse en otra suposición, que la aplicación nunca se utilizará en otros países con monedas diferentes. He visto casos donde eso resultó ser falso.
Ahora esa suposición está siendo desafiada de una nueva manera: nuevas monedas como Bitcoin se están volviendo más comunes, y no son específicas de ningún país. No es poco realista que una aplicación utilizada en un solo país todavía necesite admitir varias monedas.
Algunas personas dirán que crear o incluso usar un tipo solo por dinero es "chapado en oro" o agregar complejidad adicional más allá de los requisitos conocidos. Estoy totalmente en desacuerdo. Cuanto más ubicuo es un concepto dentro de su dominio, más importante es hacer un esfuerzo razonable para utilizar la abstracción correcta por adelantado. Si desea ver la complejidad, intente trabajar en una aplicación que solía usar decimal
y ahora hay una Currency
propiedad adicional al lado de cada decimal
propiedad.
Si usa la abstracción incorrecta por adelantado, reemplazarla más tarde será cien veces más trabajo. Eso significa potencialmente introducir defectos en el código existente, y la mejor parte es que esos defectos probablemente involucrarán cantidades de dinero, transacciones con dinero o simplemente cualquier cosa con dinero.
Y no es tan difícil usar algo que no sea decimal. Google "nuget money type" y verá que numerosos desarrolladores han creado tales abstracciones (incluyéndome a mí). Es fácil. Es tan fácil como usar en DateTime
lugar de almacenar una fecha en a string
.
Crea tu propia clase. Esto parece extraño, pero un tipo .Net es inadecuado para cubrir diferentes monedas.