sábado, 18 de setembro de 2010

Casas decimais, arredondamentos e totais

Problemas com casas decimais, arredondamentos e totais existe em muitos aplicativos, no .NET, no Excel, no Access e em muitos outros, creio até que muitos dos leitores já tiveram este tipo de problema, principalmente os que trabalham programando sistemas que envolvem algum módulo financeiro.
Imagine que você esteje programando uma rotina que é responsável por listar uma composição de preço de um determinado produto que é composto por outros produtos, ou seja,possui alguns itens com preços, conforme exemplo abaixo:

Produto: Coleção Engrenagens XPTO
Composição
Item Descrição Qtd. Valor
1 Engrenagem XPTO 1 1,2327
2 Engrenagem XPTO 1 1,2327

Valor Total do Produto: 2,4654

O total seria 2,4654 e arredondando seria 2,47 (Pode usar qualquer função "Round()" que você vai verificar isso).
Não, não é tão fácil assim como parece, imagine que o seu cliente trabalho com composição de preços com quatro casas decimais, mas ele quer que o usuário visualize somente duas casas decimais, eis aí que surge um problema.
Veja como ficaria a listagem:

Produto: Motor XPTO
Composição
Item Descrição Qtd. Valor Valor "Round()"
1 Engrenagem XPTO 1 1,2327 1,23
2 Engrenagem XPTO 1 1,2327 1,23


Valor Total do Produto: 2,4654
Valor Total do Produto com duas casas: 1,23 + 1,23 = 2,46

Arredondando o Valor do produto com quatro casas: Round(2,4654) = 2,47 !!!
Opa! Alguma coisa deu errado! Mas o que foi? Os resultados não batem, há uma diferença de um centavo. Onde ficou esse um centavo?
Esse centavo ficu no arredondamento, sim, quando arredondamos o 1,2327 , perdemos 0,0027.
Todos já conhecem a regra de arredondamento não? Aqui na wikipedia você encontra o seu funcionamento.
Como todos os aplicativos geralmente seguem essa regra de arredondamento, acabamos perdendo alguns centavos. Isso não é um problema de qualquer aplicativo ou linguagem e sim um problema da regra utilizada.
Mas como não podemos mudar a regra, temos que achar uma forma de trabalhar com os arredondamentos sem mostrar ao usuário o erro que é gerado, ou seja, precisamos "excluir" esses centavos a mais que o arredondamento faz.
Devemos então trabalhar da seguinte forma: Sempre antes de executar um cálculo que será visualizado em menos casas decimais do que os seu operadores, devemos antes, arredondar os operadores para fazer o cálculo, sendo assim, o usuário sempre vai visualizar os dados efetivos que foram calculados e não o seu arredondamento executado depois do cálculo.
Veja o exemplo abaixo em C#:

Quando arredondamos depois de fazer o cálculo para exibir para o usuário, poderá ocorrer esse erro dos centavos no arredondamento, mas se fazemos o arredondamento dos operadores antes de executar o cálculo, os dados sempre vão "bater".
Veja como o Excel também se perde:

Em resumo, sempre cheque bem os seus códigos fontes para que não ocorram problemas com os arredondamentos.

Nenhum comentário:

Postar um comentário