Posso citar três vantagens em usar double
(ou float
) em vez de decimal
:
- Usa menos memória.
- Mais rápido porque as operações matemáticas de ponto flutuante são suportadas nativamente pelos processadores.
- Pode representar um intervalo maior de números.
Mas essas vantagens parecem se aplicar apenas a operações intensivas de cálculo, como as encontradas no software de modelagem. Obviamente, duplos não devem ser usados quando a precisão é necessária, como cálculos financeiros. Então, existem razões práticas para escolher double
(ou float
) em vez de decimal
em aplicativos "normais"?
Editado para adicionar: Obrigado por todas as ótimas respostas que aprendi com elas.
Mais uma pergunta: algumas pessoas argumentaram que o dobro pode representar mais precisamente números reais. Quando declarado, eu pensaria que eles geralmente os representam com mais precisão também. Mas é uma afirmação verdadeira de que a precisão pode diminuir (às vezes significativamente) quando operações de ponto flutuante são executadas?
Respostas:
Eu acho que você resumiu as vantagens muito bem. Você está perdendo um ponto. O
decimal
tipo é apenas mais preciso na representação dos números da base 10 (por exemplo, aqueles usados em cálculos monetários / financeiros). Em geral, odouble
tipo oferece pelo menos a mesma precisão (alguém me corrija se eu estiver errado) e definitivamente maior velocidade para números reais arbitrários. A conclusão simples é: ao considerar qual usar, use sempre, adouble
menos que você precise dabase 10
precisão quedecimal
oferece.Editar:
Com relação à sua pergunta adicional sobre a diminuição da precisão dos números de ponto flutuante após as operações, esse é um problema um pouco mais sutil. De fato, a precisão (eu uso o termo de forma intercambiável para precisão aqui) diminuirá constantemente após cada operação. Isto é devido a duas razões:
Em todos os casos, se você quiser comparar dois números de ponto flutuante que, em teoria, deveriam ser equivalentes (mas foram calculados usando cálculos diferentes), é necessário permitir um certo grau de tolerância (quanto varia, mas geralmente é muito pequeno) .
Para uma visão geral mais detalhada dos casos particulares em que erros de precisão podem ser introduzidos, consulte a seção Precisão do artigo da Wikipedia . Por fim, se você quiser uma discussão profundamente aprofundada (e matemática) sobre números / operações de ponto flutuante no nível da máquina, tente ler o artigo frequentemente citado O que todo cientista da computação deve saber sobre aritmética de ponto flutuante .
fonte
double
. Os computadores modernos ainda imprimirão o valor correto, mas apenas porque "adivinhar" o resultado - não porque ele realmente seja expresso corretamente.Decimal
tipo tem 93 bits de precisão na mantissa, em comparação com cerca de 52 paradouble
. Eu gostaria que a Microsoft suportasse o formato IEEE de 80 bits, mesmo que ele tivesse que ser preenchido com 16 bytes; teria permitido uma faixa maior quedouble
ouDecimal
, muito melhor velocidade do queDecimal
, suporte para operações transcendentais (por exemplo, sin (x), log (x), etc.) e precisão que, embora não tão boa quantoDecimal
seria muito melhor do quedouble
.Você parece ter certeza dos benefícios de usar um tipo de ponto flutuante. Eu costumo projetar decimais em todos os casos, e confio em um criador de perfil para me informar se as operações em decimais estão causando gargalos ou lentidão. Nesses casos, eu irei "converter para baixo" para dobrar ou flutuar, mas apenas o faço internamente, e tentarei cuidadosamente gerenciar a perda de precisão limitando o número de dígitos significativos na operação matemática que está sendo executada.
Em geral, se seu valor é transitório (não reutilizado), você pode usar um tipo de ponto flutuante. O verdadeiro problema com os tipos de ponto flutuante são os três cenários a seguir.
123456789.1 * .000000000000000987654321
)EDITAR
De acordo com a documentação de referência em decimais C # :
Então, para esclarecer minha afirmação acima:
Eu só trabalhei em indústrias onde os decimais são favoráveis. Se você estiver trabalhando em mecanismos físicos ou gráficos, é provavelmente muito mais benéfico projetar para um tipo de ponto flutuante (flutuante ou duplo).
Decimal não é infinitamente preciso (é impossível representar precisão infinita para não integral em um tipo de dados primitivo), mas é muito mais preciso que o dobro:
EDIT 2
Em resposta ao comentário de Konrad Rudolph , o item 1 (acima) está definitivamente correto. A agregação de imprecisões realmente se compõe. Veja o código abaixo para um exemplo:
Isso gera o seguinte:
Como você pode ver, apesar de estarmos adicionando da mesma fonte constante, os resultados do duplo são menos precisos (embora provavelmente sejam arredondados corretamente), e o flutuador é muito menos preciso, a ponto de ter sido reduzido a apenas dois dígitos significativos.
fonte
Single: 667660.400000000000
enquanto o valor decimal rendeuDecimal: 666666.7000000000
. O valor flutuante é um pouco menor que mil acima do valor correto.Use decimal para os valores da base 10, por exemplo, cálculos financeiros, como outros sugeriram.
Mas o dobro é geralmente mais preciso para valores calculados arbitrariamente.
Por exemplo, se você deseja calcular o peso de cada linha em um portfólio, use o dobro, pois o resultado aumentará quase 100%.
No exemplo a seguir, doubleResult está mais próximo de 1 que decimalResult:
Então, novamente, tomando o exemplo de um portfólio:
O valor de mercado de cada linha do portfólio é um valor monetário e provavelmente seria melhor representado como decimal.
O peso de cada linha do portfólio (= Valor de mercado / SUM (Valor de mercado)) geralmente é melhor representado como o dobro.
fonte
Use um double ou um float quando não precisar de precisão, por exemplo, em um jogo de plataforma que escrevi, usei um float para armazenar as velocidades dos jogadores. Obviamente, não preciso de superprecisão aqui, porque acabo arredondando para um Int para desenhar na tela.
fonte
Em algumas Contabilidade, considere a possibilidade de usar tipos integrais em vez disso ou em conjunto. Por exemplo, digamos que as regras em que você opera exigem que cada resultado de cálculo seja transportado com pelo menos 6 casas decimais e o resultado final será arredondado para o centavo mais próximo.
Um cálculo de 1/6 de $ 100 produz $ 16.66666666666666 ..., portanto, o valor realizado em uma planilha será $ 16.666667. O dobro e o decimal devem produzir esse resultado com precisão para 6 casas decimais. No entanto, podemos evitar qualquer erro cumulativo, transmitindo o resultado como um número inteiro 16666667. Cada cálculo subsequente pode ser feito com a mesma precisão e transmitido de forma semelhante. Continuando o exemplo, calculo o imposto sobre vendas do Texas nesse valor (16666667 * .0825 = 1375000). Adicionando os dois (é uma planilha curta) 1666667 + 1375000 = 18041667. Mover o ponto decimal de volta fornece 18.041667 ou US $ 18,04.
Embora este pequeno exemplo não produza um erro cumulativo usando o dobro ou o decimal, é bastante fácil mostrar casos em que o simples cálculo do dobro ou decimal e o avanço levariam a acumular um erro significativo. Se as regras sob as quais você opera requerem um número limitado de casas decimais, armazene cada valor como um número inteiro multiplicando por 10 ^ (número necessário de casas decimais) e depois dividindo por 10 ^ (número necessário de casas decimais) para obter o valor real O valor evitará qualquer erro cumulativo.
Nas situações em que frações de centavos não ocorrem (por exemplo, uma máquina de venda automática), não há razão para usar tipos não integrais. Basta pensar nisso como contar centavos, não dólares. Eu vi código em que todos os cálculos envolviam apenas centavos inteiros, mas o uso do dobro levou a erros! Somente matemática inteira removeu o problema. Portanto, minha resposta não convencional é, quando possível, renunciar ao dobro e ao decimal.
fonte
Se você precisar interropar binário com outros idiomas ou plataformas, poderá ser necessário usar float ou double, que são padronizados.
fonte
Nota: esta postagem é baseada em informações dos recursos do tipo decimal em http://csharpindepth.com/Articles/General/Decimal.aspx e em minha própria interpretação do que isso significa. Vou assumir que Double é normal precisão dupla IEEE.
Nota 2: menor e maior neste post referem-se à magnitude do número.
Prós de "decimal".
Cons de decimal
Minha opinião é que você deve usar o "decimal" para trabalhar com dinheiro e outros casos em que a correspondência humana é exatamente importante e que você deve usar o dobro da opção padrão pelo resto do tempo.
fonte
Depende do que você precisa.
Como float e double são tipos de dados binários, você tem algumas diferenças e erros no caminho dos números das rodadas; portanto, por exemplo, double arredondaria 0,1 a 0,100000001490116, o double também arredondaria 1/3 a 0,333333334326441. Simplificando, nem todos os números reais têm representação precisa em tipos duplos
Felizmente, o C # também suporta a chamada aritmética decimal de ponto flutuante, em que os números são representados pelo sistema numérico decimal e não pelo sistema binário. Portanto, a aritmética de ponto flutuante decimal não perde a precisão ao armazenar e processar números de ponto flutuante. Isso o torna imensamente adequado para cálculos em que é necessário um alto nível de precisão.
fonte
Use pontos flutuantes se você valorizar o desempenho acima da correção.
fonte
Escolha o tipo de função do seu aplicativo. Se você precisa de precisão, como na análise financeira, respondeu à sua pergunta. Mas se o seu aplicativo puder resolver com uma estimativa, você concorda com o dobro.
Seu aplicativo precisa de um cálculo rápido ou ele terá todo o tempo do mundo para lhe dar uma resposta? Realmente depende do tipo de aplicação.
Gráfico com fome? flutuar ou dobrar é suficiente. Análise de dados financeiros, meteoro atingindo um planeta tipo de precisão? Aqueles precisariam de um pouco de precisão :)
fonte
O decimal tem bytes mais largos, o dobro é suportado nativamente pela CPU. O decimal é base 10, portanto, uma conversão decimal para o dobro ocorre enquanto um decimal é calculado.
Lembre-se de que o .NET CLR suporta apenas Math.Pow (duplo, duplo). Decimal não é suportado.
.NET Framework 4
fonte
Um valor duplo será serializado para notação científica por padrão se essa notação for menor que a exibição decimal. (por exemplo, .00000003 será 3e-8) Os valores decimais nunca serão serializados para notação científica. Ao serializar para consumo por uma parte externa, isso pode ser uma consideração.
fonte