Afinal qual tipo de dados devo usar para tratar números não inteiros: double ou decimal ? |
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:
C# - Usando Listas com elegância
C# - Trabalhando com Coleções Genéricas do tipo List(<T>)
C# - Diferentes maneira de criar uma lista de objetos
C# - Acessando dados de um dicionário ordenado
C# - Usando um Dicionário para armazenar e ..
C# - Escolhendo a coleção correta para sua ...