Usar decimal ou double no C# ?
Dúvida comum para quando estamos começando no desenvolvimento, e uma pergunta trivial dos alunos é, “qual dos tipos eu devo usar para números com decimais, uso decimal ou double ?”.
Bom, para começar, vamos lá, no C# temos os tipos double, que é utilizado para computação científica e decimal, que deve ser utilizado para cálculos financeiros.
Na tabela abaixo, podemos ver a definição dos tipos obtida no site da Microsoft:
Vale destacar que decimal é cerca de 10 vezes mais lento que double !
Ops, tem algo errado então, por que vou usar decimal ?
Vamos aos dados técnicos: os tipos float e double representam números na base 2. Por esta razão, somente números expressáveis na base 2 são representados com precisão. Praticamente isto faz com que muitos valores expressados na base 10, não sejam representados com precisão. É por isto que os tipos float e double são ruins para cálculos financeiros.
Já o tipo decimal, funciona na base 10, o que faz com que sua precisão para números expressáveis na base 10 seja maior. Como os números reais são representados na base 10, o decimal pode representar precisamente números como 0,1.
Exemplo:
Podemos notar que neste cálculo houve um arredondamento onde somado o item 10 vezes, o resultado não foi 1 !
Neste outro exemplo, temos uma situação que demonstra que em cálculos que exigem maior precisão, vemos que os valores de uma divisão com decimais, possui muito mais dígitos, fazendo com que numa soma, tenhamos o valor de volta para 1, já no caso do double, a soma é :0,9999999999999999
Resultado da execução da soma:
Portanto, vale a dica, usar decimal para valores monetários, e double e float apenas para dados científicos.
Mas o Entity Framework acaba nos pedindo para definir o tipo de dado, e caso não façamos a correta identificação nos será dado um aviso durante a inicialização da aplicação como este:
No store type was specified for the decimal property ‘NomeDoCampo’ on entity type ‘Pedidos’. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values in ‘OnModelCreating’ using ‘HasColumnType’, specify precision and scale using ‘HasPrecision’, or configure a value converter using ‘HasConversion’.
Portanto, o correto é colocar anotações para definir o tipo de dado a ser instanciado ao utilizar o banco de dados através do Entity Framework, desta forma:
Restou alguma dúvida ainda? Leia o artigo da Microsoft explicando cada tipo:
Tipos numéricos de ponto flutuante — Referência de C# | Microsoft Docs