Diferença entre decimal, float e double no .NET?

Qual é a diferença entre decimal , float e double no .NET?

Quando alguém usaria um desses?

   

float e double são tipos de ponto binário flutuantes . Em outras palavras, eles representam um número como este:

 10001.10010110011 

O número binário e a localização do ponto binário são codificados dentro do valor.

decimal é um tipo de ponto decimal flutuante . Em outras palavras, eles representam um número como este:

 12345.65789 

Novamente, o número e a localização do ponto decimal são codificados dentro do valor – isso é o que torna o decimal ainda um tipo de ponto flutuante em vez de um tipo de ponto fixo.

O importante a notar é que humanos são usados ​​para representar não-inteiros em uma forma decimal, e esperam resultados exatos em representações decimais; nem todos os números decimais são exatamente representáveis ​​no ponto flutuante binário – 0.1, por exemplo – portanto, se você usar um valor de ponto flutuante binário, obterá uma aproximação de 0.1. Você ainda obterá aproximações ao usar um ponto decimal flutuante também – o resultado da divisão de 1 por 3 não pode ser representado exatamente, por exemplo.

Quanto ao que usar quando:

  • Para valores que são “decimais naturalmente exatos”, é bom usar decimal . Isso geralmente é adequado para quaisquer conceitos inventados por humanos: os valores financeiros são o exemplo mais óbvio, mas existem outros também. Considere a pontuação dada a mergulhadores ou patinadores de gelo, por exemplo.

  • Para valores que são mais artefatos da natureza que realmente não podem ser medidos exatamente de qualquer maneira, float / double são mais apropriados. Por exemplo, dados científicos normalmente seriam representados neste formulário. Aqui, os valores originais não serão “decimais precisos” para começar, portanto, não é importante que os resultados esperados mantenham a “precisão decimal”. Tipos de pontos binários flutuantes são muito mais rápidos para trabalhar do que decimais.

Precisão é a principal diferença.

Flutuante – 7 dígitos (32 bits)

Duplo -15-16 dígitos (64 bits)

Decimal -28-29 dígitos significativos (128 bits)

Os decimais têm uma precisão muito maior e geralmente são usados ​​em aplicações financeiras que exigem um alto grau de precisão. Os decimais são muito mais lentos (até 20 vezes em alguns testes) do que um duplo / float.

Decimais e Floats / Doubles não podem ser comparados sem um casting enquanto Floats e Doubles podem. Decimais também permitem a codificação ou zeros à direita.

 float flt = 1F/3; double dbl = 1D/3; decimal dcm = 1M/3; Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm); 

Resultado:

 float: 0.3333333 double: 0.333333333333333 decimal: 0.3333333333333333333333333333 

A estrutura decimal é estritamente orientada para cálculos financeiros que exigem precisão, que são relativamente intolerantes ao arredondamento. Decimais não são adequados para aplicações científicas, no entanto, por várias razões:

  • Uma certa perda de precisão é aceitável em muitos cálculos científicos, devido aos limites práticos do problema físico ou do artefato que está sendo medido. Perda de precisão não é aceitável em finanças.
  • Decimal é muito (muito) mais lento que float e double para a maioria das operações, principalmente porque operações de ponto flutuante são feitas em binário, enquanto coisas Decimais são feitas na base 10 (ie floats e doubles são manipulados pelo hardware FPU, como MMX / SSE , enquanto decimais são calculados em software).
  • Decimal tem um intervalo de valores inaceitavelmente menor que o dobro, apesar do fato de suportar mais dígitos de precisão. Portanto, Decimal não pode ser usado para representar muitos valores científicos.

float 7 dígitos de precisão

double tem cerca de 15 dígitos de precisão

decimal tem cerca de 28 dígitos de precisão

Se você precisar de melhor precisão, use o dobro em vez de flutuar. Em CPUs modernas, ambos os tipos de dados têm quase o mesmo desempenho. O único benefício de usar o flutuador é que eles ocupam menos espaço. Praticamente importa apenas se você tiver muitos deles.

Eu achei isso interessante. O que todo cientista da computação deve saber sobre aritmética de ponto flutuante

Ninguém mencionou que

Nas configurações padrão, Floats (System.Single) e duplas (System.Double) nunca usarão verificação de estouro enquanto Decimal (System.Decimal) sempre usará verificação de estouro.

Quero dizer

 decimal myNumber = decimal.MaxValue; myNumber += 1; 

lança OverflowException .

Mas estes não fazem:

 float myNumber = float.MaxValue; myNumber += 1; 

E

 double myNumber = double.MaxValue; myNumber += 1; 

Não vou reiterar muitas informações boas (e algumas ruins) já respondidas em outras respostas e comentários, mas responderei sua pergunta de acompanhamento com uma dica:

Quando alguém usaria um desses?

Use decimal para valores contados

Use float / double para valores medidos

Alguns exemplos:

  • dinheiro (contamos dinheiro ou medimos dinheiro?)

  • distância (contamos a distância ou medimos a distância? *)

  • pontuações (contamos pontuações ou medimos pontuações?)

Nós sempre contamos dinheiro e nunca devemos medi-lo. Nós geralmente medimos a distância. Nós geralmente contamos pontuações.

* Em alguns casos, o que eu chamaria de distância nominal , podemos de fato querer “contar” a distância. Por exemplo, talvez estejamos lidando com sinais de países que mostram distâncias para cidades e sabemos que essas distâncias nunca têm mais de um dígito decimal (xxx.x km).

  1. Double e float podem ser divididos pelo inteiro zero sem uma exceção na compilation e no tempo de execução.
  2. Decimal não pode ser dividido pelo inteiro zero. A compilation sempre falhará se você fizer isso.

Os tipos de variables ​​Decimal, Double e Float são diferentes na maneira como armazenam os valores. A precisão é a principal diferença em que float é um tipo de dados de ponto flutuante de precisão simples (32 bits), double é um tipo de dados de ponto flutuante de precisão dupla (64 bits) e decimal é um tipo de dados de ponto flutuante de 128 bits.

Flutuante – 32 bits (7 dígitos)

Duplo – 64 bits (15 a 16 dígitos)

Decimal – 128 bits (28 a 29 dígitos significativos)

A principal diferença é que Floats e Doubles são tipos de ponto flutuante binários e um Decimal armazenará o valor como um tipo de ponto decimal flutuante. Assim, os Decimais têm uma precisão muito maior e são geralmente usados ​​em aplicativos de cálculo monetário (financeiro) ou científico que exigem um alto grau de precisão. Mas, no desempenho, os decimais são mais lentos que os tipos double e float.

Decimal pode 100% representar com precisão qualquer número dentro da precisão do formato decimal, enquanto Float e Double, não podem representar com precisão todos os números, números pares que estão dentro de seus respectivos formatos de precisão.

Decimal

No caso de aplicações financeiras, ou cálculos científicos, é melhor usar os tipos Decimal, pois oferece um alto nível de precisão e evita erros de arredondamento.

Duplo

Os tipos duplos são provavelmente o tipo de dados mais usado para valores reais, exceto o processamento de dinheiro.

Flutuador

Ele é usado principalmente em bibliotecas gráficas porque exige muito alto poder de processamento, também usa situações que podem suportar erros de arredondamento.

Inteiros, como foi mencionado, são números inteiros. Eles não podem armazenar o ponto, como .7, .42 e .007. Se você precisa armazenar números que não são números inteiros, você precisa de um tipo diferente de variável. Você pode usar o tipo duplo ou o tipo flutuante. Você define esses tipos de variables ​​exatamente da mesma maneira: em vez de usar a palavra int , digite double ou float . Como isso:

 float myFloat; double myDouble; 

( float é a abreviação de “ponto flutuante” e significa apenas um número com um ponto no final.)

A diferença entre os dois está no tamanho dos números que eles podem conter. Para float , você pode ter até 7 dígitos no seu número. Para o double , você pode ter até 16 dígitos. Para ser mais preciso, aqui está o tamanho oficial:

 float: 1.5 × 10^-45 to 3.4 × 10^38 double: 5.0 × 10^-324 to 1.7 × 10^308 

float é um número de 32 bits e double é um número de 64 bits.

Clique duas vezes no novo botão para acessar o código. Adicione as seguintes três linhas ao seu código de botão:

 double myDouble; myDouble = 0.007; MessageBox.Show(myDouble.ToString()); 

Pare seu programa e retorne à janela de codificação. Altere esta linha:

 myDouble = 0.007; myDouble = 12345678.1234567; 

Execute o seu programa e clique no seu botão duplo. A checkbox de mensagem exibe corretamente o número. No entanto, adicione outro número no final e o C # será novamente arredondado para cima ou para baixo. A moral é se você quer precisão, tenha cuidado com o arredondamento!

Este foi um tópico interessante para mim, já que hoje, acabamos de ter um pequeno erro desagradável, com o decimal tendo menos precisão do que um float .

Em nosso código C #, estamos lendo valores numéricos de uma planilha do Excel, convertendo-os em um decimal e enviando esse decimal novamente para um Serviço para salvar em um database do SQL Server .

 Microsoft.Office.Interop.Excel.Range cell = … object cellValue = cell.Value2; if (cellValue != null) { decimal value = 0; Decimal.TryParse(cellValue.ToString(), out value); } 

Agora, para quase todos os nossos valores do Excel, isso funcionou lindamente. Mas para alguns valores muito pequenos do Excel, usando decimal.TryParse perdeu o valor completamente. Um exemplo é

  • cellValue = 0.00006317592

  • Decimal.TryParse (cellValue.ToString (), out value); // retornaria 0

A solução, bizarramente, era converter os valores do Excel em uma double primeiro e depois em um decimal :

 Microsoft.Office.Interop.Excel.Range cell = … object cellValue = cell.Value2; if (cellValue != null) { double valueDouble = 0; double.TryParse(cellValue.ToString(), out valueDouble); decimal value = (decimal) valueDouble; … } 

Mesmo que o double tenha menos precisão do que um decimal , isso na verdade garantiu que pequenos números ainda seriam reconhecidos. Por alguma razão, double.TryParse era realmente capaz de recuperar números tão pequenos, enquanto decimal.TryParse os decimal.TryParse como zero.

Ímpar. Muito estranho.

flutuar ~ ± 1,5 x 10-45 a ± 3,4 x 1038 ——– 7 figuras
duplo ~ ± 5,0 x 10-324 a ± 1,7 x 10308 —— 15 ou 16 figuras
decimal ~ ± 1,0 x 10-28 a ± 7,9 x 1028 ——– 28 ou 29 figuras

Para aplicações como jogos e sistemas embarcados, onde a memory e o desempenho são críticos, o float é geralmente o tipo numérico de escolha, pois é mais rápido e metade do tamanho de um duplo. Inteiros costumavam ser a arma de escolha, mas o desempenho de ponto flutuante ultrapassou o número inteiro em processadores modernos. Decimal está certo!

Os tipos de variables ​​Decimal, Double e Float são diferentes na maneira como armazenam os valores. A precisão é a principal diferença em que float é um tipo de dados de ponto flutuante de precisão simples (32 bits), double é um tipo de dados de ponto flutuante de precisão dupla (64 bits) e decimal é um tipo de dados de ponto flutuante de 128 bits.

Flutuante – 32 bits (7 dígitos)

Duplo – 64 bits (15 a 16 dígitos)

Decimal – 128 bits (28 a 29 dígitos significativos)

Mais sobre … a diferença entre Decimal, Float e Double

O problema com todos esses tipos é que uma certa imprecisão subsiste E que esse problema pode ocorrer com pequenos números decimais, como no exemplo a seguir

 Dim fMean as Double = 1.18 Dim fDelta as Double = 0.08 Dim fLimit as Double = 1.1 If fMean - fDelta < fLimit Then bLower = True Else bLower = False End If 

Pergunta: Qual valor a variável bLower contém?

Resposta: Em uma máquina de 32 bits, o bower contém TRUE !!!

Se eu replace Double por Decimal, bLower contém FALSE, que é a boa resposta.

Em dobro, o problema é que fMean-fDelta = 1.09999999999 que é menor que 1.1.

Cuidado: Eu acho que o mesmo problema pode certamente existir para outro número porque Decimal é apenas um duplo com maior precisão e a precisão sempre tem um limite.

De fato, Double, Float e Decimal correspondem a decimal BINARY em COBOL!

É lamentável que outros tipos numéricos implementados no COBOL não existam no .net. Para aqueles que não conhecem o COBOL, existem no tipo numérico COBOL

 BINARY or COMP like float or double or decimal PACKED-DECIMAL or COMP-3 (2 digit in 1 byte) ZONED-DECIMAL (1 digit in 1 byte) 

A principal diferença entre cada um deles é a precisão.

float é um número de 32-bit , o double é um número de 64-bit e decimal é um número de 128-bit .

Em palavras simples:

  1. Os tipos de variables ​​Decimal, Double e Float são diferentes na maneira como armazenam os valores.
  2. A precisão é a principal diferença (Observe que essa não é a única diferença) em que float é um tipo de dados de ponto flutuante de precisão simples (32 bits), double é um tipo de dados de ponto flutuante de precisão dupla (64 bits) e decimal é de 128 bits tipo de dados de ponto flutuante.
  3. A tabela de resumo:

 /========================================================================================== Type Bits Have up to Approximate Range /========================================================================================== float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38) double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308) decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28) /========================================================================================== 

Você pode ler mais aqui , Float , Double e Decimal .