Qual é o melhor tipo de dados para usar em dinheiro em c #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
Qual é o melhor tipo de dados para usar em dinheiro em c #?
using System.ComponentModel.DataAnnotations;
... [DataType(DataType.Currency)]
msdn.microsoft.com/en-us/library/…
Respostas:
Como é descrito em decimal como:
A palavra-chave decimal indica um tipo de dados de 128 bits. Comparado aos tipos de ponto flutuante, o tipo decimal tem mais precisão e um intervalo menor, o que o torna apropriado para cálculos financeiros e monetários .
Você pode usar um decimal da seguinte maneira:
decimal myMoney = 300.5m;
O tipo de valor decimal representa números decimais que variam de 79.228.162.514.264.337.593.543.950.335 positivo a 79.228.162.514.264.337.593.543.950.335 positivo. O tipo de valor decimal é apropriado para cálculos financeiros que exigem grandes números de dígitos integrais e fracionais significativos e sem erros de arredondamento. O tipo decimal não elimina a necessidade de arredondamento. Em vez disso, minimiza erros devido a arredondamentos.
Eu gostaria de apontar para esta excelente resposta do zneak sobre por que o dobro não deve ser usado.
Use o padrão Money de Patterns of Enterprise Application Architecture ; especifique o valor como decimal e a moeda como um enum.
Money
nuget tem um link morto do github para o site do projeto, então ... não há documentos?
Decimal. Se você escolher o dobro, ficará aberto a erros de arredondamento
double
pode introduzir erros de arredondamento porque o ponto flutuante não pode representar todos os números exatamente (por exemplo, 0,01 não tem representação exata no ponto flutuante). Decimal
, Por outro lado, não representam números exatamente . (O trade-off Decimal
tem um alcance menor que o ponto flutuante) O ponto flutuante pode gerar erros de arredondamento * inadvertidos * (por exemplo 0.01+0.01 != 0.02
). Decimal
pode dar-lhe erros de arredondamento, mas só quando você pediu para ele (por exemplo, Math.Round(0.01+0.02)
retorna zero)
double
e aplicar cuidadosamente a escala e o arredondamento específico do domínio, quando apropriado, poderá ser perfeitamente preciso. Se alguém é desleixado em seu arredondamento, decimal
pode produzir resultados que são semanticamente incorretos (por exemplo, se somarmos vários valores que deveriam ser arredondados para o centavo mais próximo, mas na verdade não os rodeiam primeiro). A única coisa boa decimal
é que o dimensionamento é incorporado.
decimal tem um alcance menor, mas maior precisão - para que você não perca todos esses centavos ao longo do tempo!
Detalhes completos aqui:
Concorde com o padrão Money: o manuseio de moedas é muito complicado quando você usa decimais.
Se você criar uma classe Currency, poderá colocar toda a lógica relacionada ao dinheiro, incluindo um método ToString () correto, mais controle dos valores de análise e melhor controle das divisões.
Além disso, com uma classe Currency, não há chance de misturar dinheiro sem intenção com outros dados.
Outra opção (especialmente se você está rolando sua própria classe) é usar um int ou um int64 e designar os quatro dígitos inferiores (ou possivelmente até 2) como "à direita do ponto decimal". Então, "nas bordas", você precisará de "* 10000" na entrada e "/ 10000" na saída. Esse é o mecanismo de armazenamento usado pelo SQL Server da Microsoft, consulte http://msdn.microsoft.com/en-au/library/ms179882.aspx
A importância disso é que todo o seu somatório pode ser feito usando aritmética inteira (rápida).
A maioria dos aplicativos com os quais trabalhei usam decimal
para representar dinheiro. Isso se baseia no pressuposto de que o aplicativo nunca se preocupará com mais de uma moeda.
Essa suposição pode basear-se em outra suposição, de que o aplicativo nunca será usado em outros países com moedas diferentes. Já vi casos em que isso provou ser falso.
Agora essa suposição está sendo desafiada de uma nova maneira: novas moedas como Bitcoin estão se tornando mais comuns e não são específicas para nenhum país. Não é irreal que um aplicativo usado em apenas um país ainda precise suportar várias moedas.
Algumas pessoas dirão que criar ou mesmo usar um tipo apenas por dinheiro é "ouro", ou acrescenta complexidade extra além dos requisitos conhecidos. Eu discordo fortemente. Quanto mais onipresente estiver um conceito no seu domínio, mais importante será fazer um esforço razoável para usar a abstração correta antecipadamente. Se você quiser ver a complexidade, tente trabalhar em um aplicativo que costumava usar decimal
e agora há uma Currency
propriedade adicional ao lado de cada decimal
propriedade.
Se você usar a abstração errada no início, substituí-la mais tarde será cem vezes mais trabalhos. Isso significa potencialmente introduzir defeitos no código existente, e a melhor parte é que esses defeitos provavelmente envolverão quantias em dinheiro, transações com dinheiro ou apenas qualquer coisa com dinheiro.
E não é tão difícil usar algo que não seja decimal. Google "nuget money type" e você verá que vários desenvolvedores criaram tais abstrações (inclusive eu.) É fácil. É tão fácil quanto usar, em DateTime
vez de armazenar uma data em um arquivo string
.
Crie sua própria classe. Isso parece estranho, mas um tipo .Net é inadequado para cobrir diferentes moedas.