C# - double ou decimal, Oh! Dúvida cruel


 Afinal qual tipo de dados devo usar para tratar números não inteiros: double ou decimal ?

Quero iniciar dizendo que este artigo foi baseado em diversos posts que encontrei na web, assim fiz um apanhado
geral e apresento aqui um resumo que conclui ser o mais coerente.

Um conceito importante que devemos levar em conta quando tratamos com números na plataforma .NET é o
conceito de precisão e exatidão cujas definições podem ser:

Precisão - refere-se à proximidade de duas ou mais medidas entre si. Assim se fizermos 10 medidas obtendo 2,56,
podemos dizer que a medida é muito precisa.

Exatidão - refere-se à proximidade de um valor com valor conhecido. Se você pesar um objeto e obter 6,25 Kg e
souber que o peso real deste objeto é 9,00 Kg então sua medida não é muito exata.

Existem também a precisão aritmética que refere-se ao número de dígitos usados para representar um número. 
Assim, o número 4,59 é menos preciso que  4,5875648.

Desta forma, quando realizamos operações matemáticas em um computador desejamos que ele seja exato e
preciso.
Assim 5x7 deve ser sempre 35 não importa o número de vezes que isso for calculado.

Ocorre que a medida da extensão da exatidão e precisão que queremos vai ter um custo em termos de
desempenho
em nosso sistema.

Dependendo do cenário, podemos abrir mão de um ou outro, perdemos assim alguma precisão aritmética e
obtemos desempenho. O inverso também é verdadeiro: se precisarmos que os valores sejam aritmeticamente
precisos, gastaremos mais tempo calculando esses valores. Esquecer isso pode levar a problemas de desempenho
incríveis, problemas que podem ser resolvidos usando o tipo correto para o problema correto.

Para não estender mais essas considerações vamos logo ao que interessa para tratar números não inteiros devo
usar double ou decimal como tipo de dados ?

O desempenho de decimal e double

O código a seguir faz uma medida do desempenho entre o uso do double e decimal.

using System;
using System.Diagnostics;
namespace CShp_Teste1
{
    class Program
    {
        static private int iteracoes = 100000000;
        static void Main(string[] args)
        {
            DoubleTeste();
            DecimalTeste();
            Console.ReadLine();
        }
        static private void DoubleTeste()
        {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Double z = 0;
                for (int i = 0; i < iteracoes; i++)
                {
                    Double x = i;
                    Double y = x * i;
                    z += y;
                }
                watch.Stop();
                Console.WriteLine("Double: " + watch.ElapsedTicks);
                Console.WriteLine(z);
            }
        static private void DecimalTeste()
        {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Decimal z = 0;
                for (int i = 0; i < iteracoes; i++)
                {
                    Decimal x = i;
                    Decimal y = x * i;
                    z += y;
                }
                watch.Stop();
                Console.WriteLine("Decimal: " + watch.ElapsedTicks);
                Console.WriteLine(z);
        }
    }
}

Executando o projeto teremos o seguinte resultado:

Como vemos, para calcular o double foram gastos 3846650 ticks enquanto para decimal gastou-se 47673776
ticks
,  ou seja gastou-se quase 13 vezes mais tempo. (Os valores podem variar conforme seu processador)

Mas por quê ?

Por que o tipo decimal gasta mais de dez vezes do que tipo double ?

O tipo de dados double usa a matemática da base 2, enquanto o decimal usa a matemática da base 10. A
matemática da base 2 é muito mais rápida para os computadores calcularem.

Além disso, o double está relacionado ao desempenho, enquanto o decimal está relacionado à precisão.

Ao usar double, você aceita uma compensação conhecida: não será super preciso nos seus cálculos, mas receberá
uma resposta aceitável rapidamente.

Considerando que, com decimal, a precisão é incorporada ao seu tipo: deve ser usada para cálculos com valores
monetários, visto que quando envolve dinheiro ninguem quer perder, e também onde a precisão é um requisito
crítico.

Assim se você quer desempenho use double se você quer precisão use decimal.

Apenas esteja certo de fazer a escolha certa para o tipo de cálculo adequado.

E estamos conversados...

"E percorria Jesus todas as cidades e aldeias, ensinando nas sinagogas deles, e pregando o evangelho do reino, e curando todas as enfermidades e moléstias entre o povo."
Mateus 9:35

Referências:


José Carlos Macoratti