Qual é a diferença entre decimal
, float
e double
em .NET?
Quando alguém usaria um desses?
.net
floating-point
double
decimal
PC Luddite
fonte
fonte
Respostas:
float
edouble
são tipos de pontos binários flutuantes . Em outras palavras, eles representam um número como este:O número binário e a localização do ponto binário são ambos codificados no valor.
decimal
é um tipo de ponto decimal flutuante . Em outras palavras, eles representam um número como este:Novamente, o número e a localização do ponto decimal são codificados no valor - é o que torna
decimal
ainda um tipo de ponto flutuante em vez de um tipo de ponto fixo.O importante a ser observado é que os humanos estão acostumados a 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 - o resultado da divisão de 1 por 3 não pode ser exatamente representado, por exemplo.
Quanto ao que usar quando:
Para valores que são "decimais naturalmente exatos", é bom usar
decimal
. Isso geralmente é adequado para qualquer conceito inventado por humanos: os valores financeiros são o exemplo mais óbvio, mas também existem outros. Considere a pontuação atribuída a mergulhadores ou patinadores no gelo, por exemplo.Para valores que são mais artefactos da natureza que não pode realmente ser medidos exatamente de qualquer maneira,
float
/double
são mais apropriadas. Por exemplo, dados científicos geralmente 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". Os tipos de ponto binário flutuante são muito mais rápidos do que os decimais.fonte
float
/double
Geralmente não representam números como101.101110
, normalmente ele é representado como algo como1101010 * 2^(01010010)
- um expoentefloat
é uma palavra-chave alias em C # e não é do tipo .Net. éSystem.Single
..single
edouble
são tipos de pontos binários flutuantes.Precisão é a principal diferença.
Flutuador - 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 aplicativos financeiros que exigem um alto grau de precisão. Os decimais são muito mais lentos (até 20 vezes mais em alguns testes) do que um double / float.
Decimais e Bóias / Dobros não podem ser comparados sem um elenco, enquanto Bóias e Dobros podem. Os decimais também permitem a codificação ou zeros à direita.
Resultado:
fonte
0.1
- isso raramente acontece no mundo real! Qualquer formato de armazenamento finito confunde um número infinito de valores possíveis com um número finito de padrões de bits. Por exemplo,float
conflitará0.1
e0.1 + 1e-8
, enquantodecimal
conflitará0.1
e0.1 + 1e-29
. Certamente, dentro de um determinado intervalo , certos valores podem ser representados em qualquer formato com perda zero de precisão (por exemplo,float
pode armazenar qualquer número inteiro até 1.6e7 com perda zero de precisão) - mas isso ainda não é precisão infinita .0.1
é um valor especial ! A única coisa que torna0.1
"melhor" do que0.10000001
é porque os seres humanos gostam da base 10. E mesmo com umfloat
valor, se você inicializar dois valores0.1
da mesma maneira, ambos terão o mesmo valor . Só que esse valor não será exatamente0.1
- será o valor mais próximo do0.1
que pode ser representado exatamente como afloat
. Claro, com flutuadores binários(1.0 / 10) * 10 != 1.0
, mas também com flutuadores decimais(1.0 / 3) * 3 != 1.0
. Nem é perfeitamente preciso.double a = 0.1; double b = 0.1;
,a == b
será verdade . É apenas issoa
e ambos nãob
serão exatamente iguais . Em C #, se você o fizer , também será verdadeiro. Mas, nesse caso, nem de nem será exatamente igual - ambos irão igual . Nos dois casos, alguma precisão é perdida devido à representação. Você teimosamente diz que tem precisão "infinita", o que é falso .0.1
decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
a == b
a
b
1/3
0.3333...
decimal
A estrutura decimal é estritamente voltada para cálculos financeiros que exigem precisão, que são relativamente intolerantes ao arredondamento. Os decimais não são adequados para aplicações científicas, no entanto, por várias razões:
fonte
Veja aqui para mais informações .
fonte
Não reiterarei toneladas de informações boas (e ruins) já respondidas em outras respostas e comentários, mas responderei sua pergunta de acompanhamento com uma dica:
Use decimal para valores contados
Use float / double para valores medidos
Alguns exemplos:
dinheiro (contamos dinheiro ou medimos dinheiro?)
distance (contamos distância ou medimos distância? *)
pontuações (contamos pontuações ou medimos pontuações?)
Sempre contamos dinheiro e nunca devemos medi-lo. Normalmente medimos a distância. Contamos frequentemente pontuações.
* Em alguns casos, o que eu chamaria de distância nominal , podemos realmente 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).
fonte
float
7 dígitos de precisãodouble
tem cerca de 15 dígitos de precisãodecimal
tem cerca de 28 dígitos de precisãoSe você precisar de uma precisão melhor, use duplo em vez de flutuar. Nas CPUs modernas, os dois tipos de dados têm quase o mesmo desempenho. O único benefício de usar float é que eles ocupam menos espaço. Praticamente importa apenas se você tiver muitos deles.
Achei isso interessante. O que todo cientista da computação deve saber sobre aritmética de ponto flutuante
fonte
double
adequado em aplicativos de contabilidade nesses casos (e basicamente apenas naqueles casos) em que nenhum tipo inteiro maior que 32 bits estava disponível, edouble
estava sendo usado como se fosse um tipo inteiro de 53 bits (por exemplo, para manter um número inteiro de centavos ou um número inteiro de centésimos de centavo). Atualmente, não há muito uso para essas coisas, mas muitas linguagens ganharam a capacidade de usar valores de ponto flutuante de precisão dupla muito antes de ganharem matemática inteira de 64 bits (ou, em alguns casos, até 32 bits!).Real
poderia representar valores de até 1,8E + 19 com precisão de unidade. Eu acho que seria muito mais saudável para uma aplicação de contabilidade de usarReal
para representar um número inteiro de moedas de um centavo do que ...double
tipo com precisão de unidade de até 9E15. Se for necessário armazenar números inteiros maiores que o maior tipo inteiro disponível, o usodouble
poderá ser mais simples e eficiente do que tentar falsificar a matemática de multiprecisão, especialmente porque os processadores têm instruções para executar 16x16-> 32 ou. ..Ninguém mencionou isso
Quero dizer
lança OverflowException .
Mas estes não:
&
fonte
float.MaxValue+1 == float.MaxValue
, assim comodecimal.MaxValue+0.1D == decimal.MaxValue
. Talvez você quis dizer algo comofloat.MaxValue*2
?System.Decimal
exceção é lançada pouco antes de se tornar incapaz de distinguir unidades inteiras, mas se um aplicativo supostamente estiver lidando com, por exemplo, dólares e centavos, isso pode ser tarde demais.fonte
decimal
por zero (CS0020), e o mesmo se aplica aos literais integrais. No entanto, se um valor decimal em tempo de execução for dividido por zero, você receberá uma exceção e não um erro de compilação.Inteiros, como foi mencionado, são números inteiros. Eles não podem armazenar algo do ponto, como 0,7, 0,42 e 0,007. Se você precisar armazenar números que não sejam números inteiros, precisará de um tipo diferente de variável. Você pode usar o tipo duplo ou flutuante. Você configura esses tipos de variáveis exatamente da mesma maneira: em vez de usar a palavra
int
, você digitadouble
oufloat
. Como isso:(
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. Paradouble
s, você pode ter até 16 dígitos. Para ser mais preciso, eis o tamanho oficial:float
é um número de 32 bits edouble
é um número de 64 bits.Clique duas vezes no seu novo botão para obter o código. Adicione as três linhas a seguir ao código do botão:
Pare o seu programa e retorne à janela de codificação. Mude esta linha:
Execute seu programa e clique no botão duplo. A caixa de mensagem exibe corretamente o número. Adicione outro número no final, porém, e o C # será novamente arredondado para cima ou para baixo. A moral é que se você quer precisão, tenha cuidado ao arredondar!
fonte
fonte
decimal
é realmente armazenado no formato decimal (em oposição à base 2; portanto, não perde ou arredonda os dígitos devido à conversão entre os dois sistemas numéricos); além disso,decimal
não tem conceito de valores especiais como NaN, -0, ∞ ou -∞.Esta tem sido uma discussão interessante para mim, pois hoje, tivemos apenas um bug desagradável, por
decimal
ter menos precisão que afloat
.Em nosso código C #, estamos lendo valores numéricos de uma planilha do Excel, convertendo-os em um
decimal
e enviando-osdecimal
novamente para um Serviço para salvar em um banco de dados do SQL Server .Agora, para quase todos os nossos valores do Excel, isso funcionou perfeitamente. Mas, para alguns valores muito pequenos do Excel, o uso
decimal.TryParse
do valor foi perdido completamente. Um exemplo écellValue = 0.00006317592
Decimal.TryParse (cellValue.ToString (), valor out); // retornaria 0
A solução, estranhamente, foi converter os valores do Excel em um
double
primeiro e depois em umdecimal
:Embora
double
tenha menos precisão que adecimal
, isso realmente garantiu que pequenos números ainda seriam reconhecidos. Por alguma razão,double.TryParse
foi realmente capaz de recuperar números tão pequenos, enquantodecimal.TryParse
os definiria como zero.Ímpar. Muito estranho.
fonte
decimal.Parse("0.00006317592")
funciona - você tem algo mais acontecendo. - Notação possivelmente científica?Para aplicativos como jogos e sistemas incorporados nos quais a memória e o desempenho são críticos, o float geralmente é o tipo numérico de escolha, pois é mais rápido e tem a metade do tamanho de um dobro. Os números inteiros costumavam ser a arma preferida, mas o desempenho do ponto flutuante ultrapassou o número inteiro nos processadores modernos. Decimal está certo!
fonte
Os tipos de variável Decimal, Double e Float são diferentes na maneira como eles armazenam os valores. Precisão é a principal diferença em que float é um tipo de dados de ponto flutuante de precisão única (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.
Flutuador - 32 bits (7 dígitos)
Duplo - 64 bits (15-16 dígitos)
Decimal - 128 bits (28-29 dígitos significativos)
Mais sobre ... a diferença entre Decimal, Float e Double
fonte
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
Pergunta: Qual valor a variável bLower contém?
Resposta: Em uma máquina de 32 bits, o bLower contém VERDADEIRO !!!
Se substituir Double por Decimal, o bLower conterá FALSE, que é a boa resposta.
Em dobro, o problema é que fMean-fDelta = 1.09999999999 é menor que 1.1.
Cuidado: Eu acho que esse mesmo problema certamente pode 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 ao 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 COBOL, existem em COBOL seguindo o tipo numérico
fonte
Em palavras simples:
fonte
Decimal
adequado para aplicações financeiras e é o principal critério a ser usado ao decidir entreDecimal
eDouble
. É raro que aDouble
precisão não seja suficiente para aplicações científicas, por exemplo (eDecimal
muitas vezes não é adequada para aplicações científicas devido ao seu alcance limitado).A principal diferença entre cada um deles é a precisão.
float
é um32-bit
número,double
é um64-bit
número edecimal
é um128-bit
número.fonte
Decimal de 128 bits (28-29 dígitos significativos) No caso de aplicativos financeiros, é melhor usar os tipos decimais, pois fornece um alto nível de precisão e é fácil evitar erros de arredondamento. Use decimal para matemática não inteira onde a precisão é necessária (por exemplo, dinheiro e moeda)
Tipo duplo de 64 bits (15 a 16 dígitos) Os tipos duplos são provavelmente o tipo de dados mais usado para valores reais, exceto manipulando dinheiro. Use double para matemática não inteira, onde a resposta mais precisa não é necessária.
Flutuar 32 bits (7 dígitos) É usado principalmente em bibliotecas gráficas, porque demandas muito altas de capacidade de processamento também usavam situações que podem suportar erros de arredondamento.
Decimals
são muito mais lentos que umdouble/float
.Decimals
eFloats/Doubles
não pode ser comparado sem um elenco enquantoFloats
eDoubles
pode.Decimals
também permite a codificação ou zeros à direita.fonte
Para definir decimal, flutuar e dobrar em .Net (c #)
você deve mencionar valores como:
e verifique os resultados.
E os bytes ocupados por cada um são
fonte