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.