Pergunta

Alguém pode explicar essa estranheza:

Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected

Na sequência do acima

result = 8.02 * 100 ' result = 802.0 as expected
Foi útil?

Solução

Single (ou float) só tem sete dígitos significativos, por isso, tudo o que pode ser impresso além daqueles é muito bonito falso de qualquer maneira. Este é um artefacto normal de aritmética de ponto flutuante. Você só pode contar com até 4 dígitos depois do ponto decimal com o seu número (como três dígitos significativos já estão antes do ponto decimal).

Mais elaborado, os números de 8.01 e 8,02 não pode ser representado usando exactamente armazenamento binário (como nem 0,01 0,02 nem pode ser representado exactamente com somas de fracções de forma a 1/2 n ). Os detalhes podem variar de número para número, mas você pode ver dígitos estranhos fora da faixa de precisão normal quando o uso de tais números.

Isto não afeta o fato de que 801 e 802 pode ser representado exatamente, mas você não tem nenhum número exato para começar neste caso.

ETA: Na verdade, o que você vê quando você incluir o cálculo diretamente é apenas isso: O compilador irá avaliar o cálculo para você e 802 Basta escrever para o programa. Você pode usar o refletor para verificar isso. Também flutuante literais ponto no código fonte são provavelmente Double por padrão, então você tem precisão maior muito para começar aqui. Se result é um Single isso será downcasted para Single e o erro na dígito 16 depois do ponto decimal é simplesmente jogado fora, uma vez que não pode caber em Single de qualquer maneira.

Outras dicas

Isto é devido a uma limitação na forma como números de ponto flutuante são representados na memória. Ter uma leitura através do wikipedia página para o lowdown completo - não é um erro, ou algo específico para .net.

EDIT:. Esses dois artigos são olhar uma pena demasiado (o último é matemática pesada)

Se o que você precisa é comparar valores de ponto flutuante, consulte aqui: Comparando ponto flutuante valores

Single e Double em .NET são representadas como números de ponto flutuante e, infelizmente, armazenar esses tipos de números não é preciso. Você vai ter pequenas discrepâncias quando se trabalha com 'Single' e os números de 'duplo'.

No entanto, há uma alternativa - NET tem um tipo Decimal que é muito melhor em lidar com esses números. Ele ainda não é perfeito (ver http://www.yoda.arachsys.com/csharp/ decimal.html - em particular o último parágrafo), mas será muito melhor em representar quantidades como o dinheiro

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top