C# - Usando o ponto flutuante nos cálculos


 Neste artigo vou rever conceitos básicos do C# apresentando o tratamento de variáveis do tipo ponto flutuante em cálculos.


As limitações de uma variável do tipo int podem ser inaceitáveis para alguns tipos de aplicações. O intervalo em geral não é um problema; o intervalo de dois milhões de bits de um inteiro de 64 bits deve ser suficiente para a maioir dos problemas envolvendo inteiros.

No entanto, o fato de que um int estar limitado a números inteiros pode ser o fator determinante na sua não utilização em muitos cenários. Em alguns casos, você precisa de números que podem ter uma parte fracionária diferente de zero. Esses números podem ser representados pelos números reais.

Na linguagem C# os números reais podem ser de ponto flutuante e decimal onde o ponto flutuante é o tipo mais comum.

Para declarar uma variável como sendo um número de ponto flutuante podemos usar os tipos float e double na linguagem C#.(temos também o tipo decimal)

A tabela a seguir mostra a precisão e os intervalos aproximados dos tipos de ponto flutuante: para float e double

Tipo Intervalo aproximado Precisão Uso
float ±1,5e−45 para ±3,4e38 6 a 7 dígitos float f = 12.5F;
double ±5,0e−324 para ±1,7e308 15 a 16 dígitos double d = 12.5;

Se você estiver pensando que float é o tipo padrão para os número de ponto flutuante, se enganou... O tipo padrão para estes números é double

Assim se você não declarar o tipo de uma variável, o C# vai inferir como double, veja:

Tratando a precisão do resultado com ponto flutuante

A coluna Precisão na tabela cima refere-se ao número de dígitos significativos que esse tipo de variável pode representar.

Por exemplo, o número 0.555 ... possui uma sequência interminável de cincos. (uma dízima periódica simples)

No entanto, uma variável do tipo float possui de 6 a 7 dígitos significativos de precisão, o que significa que números após o sexto dígito serão ignorados.

Veja o resultado obtido da divisão de 5/9 que nos dá o número 0,5555556 com 7 dígitos significativos quando usamos o tipo float.

Agora vejamos como fica se usarmos o tipo double para representar o mesmo resultado:

Agora vemos que o resultado é expresso com uma precisão de 15 dígitos : 0,555555555555556

A lição aprendida aqui é que você deve usar variáveis do tipo double para representar números reais quando a precisão do cálcula for relevante, a menos que você tenha uma razão específica para não fazer isso.

Tomando cuidado ao fazer cálculos financeiros com ponto flutuante

Ao tratar com números de ponto flutuante e usar os tipos float e double você tem que tomar muito cuidado com o resultado obtido em cálculos.

Veja esse exemplo:

1- ) Vamos supor que o preço de um produto é R$ 4,99 e você deseja saber o valor total de 17 itens desse produto.

Abaixo temos o código usado para fazer o cálculo usando o tipo float para o preço do produto e naturalmente você vai esperaro resultado de R$ 84,83 visto que 4.99x17 = 84.83. Certo ?

Você esperava 84,83 mas o resultado obtido foi 84,82999.  Para obter o resultado correto você deve usar o tipo decimal.

Agora veja esse outro exemplo:

2- ) Você vende um produto que custa R$ 100,00 e você esta dando um desconto de 10% sobre o valor do produto.

Abaixo temos o código que calcula o valor final do produto com desconto usando o tipo float para desconto e int para o preço final visto que seu preço é inteiro.

Note que o valor esperado seria 90 mas você obteve 89. Seus clientes devem ficar muito felizes com esse 1% a mais de desconto.

Para obter o valor correto use :  decimal precoFinalComDesconto = (decimal)(precoProduto * (1 - desconto));

Conclusão

Para qualquer cálculo que envolva dinheiro ou finanças, o tipo Decimal deve ser sempre utilizado.

Só este tipo tem a precisão adequada para evitar os erros críticos de arredondamento.

Por quê ?

O tipo de dados Decimal é simplesmente um tipo de ponto flutuante que é representado internamente como base 10 ao invés de base dois.

Obviamente, com base 10 (o nosso sistema de numeração real) qualquer número decimal pode ser construído para o valor exato ter que realizar aproximações.

O tipo Decimal é realmente uma estrutura que contém funções sobrecarregadas para todas as operações matemáticas e de comparação, ou seja, ele é realmente uma implementação da aritmética de base 10.

E estamos conversados...

"Levantai os vossos olhos para os céus, e olhai para a terra em baixo, porque os céus desaparecerão como a fumaça, e a terra se envelhecerá como roupa, e os seus moradores morrerão semelhantemente; porém a minha salvação durará para sempre, e a minha justiça não será abolida."
Isaías 51:6

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Referências:


José Carlos Macoratti