Atualmente estou desenvolvendo um sistema ERP (Enterprise Resource Planning) e preciso tomar decisões quanto ao tipo de dados a serem usados para lidar com cálculos e outros valores numéricos dentro da aplicação.
Eu sei que Java oferece diversas opções para lidar com números decimais, como BigDecimal e Double. Entendo que cada um tem suas vantagens e desvantagens, mas quero garantir que escolho o mais adequado para manter a precisão e a eficiência em meu sistema.
Aqui estão alguns contextos específicos onde preciso aplicar cálculos:
- Faturamento e Pagamentos: lidar com preços, impostos, descontos, etc.
- Folha de pagamento e contabilidade:
- Gestão de estoque: Incluindo preços unitários e custos de produtos.
Estou inclinado a usar o BigDecimal para operações financeiras devido à precisão que oferece, mas estou preocupado com o impacto no desempenho. Por outro lado, Double pode ser mais eficiente em termos de velocidade, mas pode introduzir erros de arredondamento.
Que recomendações você tem para lidar com esses casos em um ERP? Em quais situações seria preferível usar BigDecimal e quando Double? Existem padrões ou práticas recomendadas que devo seguir?
Evite ponto flutuante por dinheiro
A tecnologia de ponto flutuante troca precisão por velocidade de execução.
Em Java, os tipos primitivos
float
edouble
são tipos de ponto flutuante. O mesmo acontece com suas classes wrapperFloat
eDouble
. Nunca use-os onde a precisão é importante. Isso significa nunca por dinheiro.Use um
BigDecimal
ou números inteirosEm vez disso, quantias fracionárias de dinheiro devem ser tratadas de acordo com uma destas abordagens:
BigDecimal
objetos. Esse tipo é muito mais lento que o ponto flutuante, mas preciso. A sintaxe é mais desajeitada que os literais numéricos, é claro. Mas por outro lado, além da precisão, você obtém métodos úteis, como Banker's Rounding .long
). Para rastrear o dólar até o décimo de centavo, multiplique por mil para representar moinhos (₥).Tabela de tipos de dinheiro fracionário
float
&double
1.23d
new BigDecimal( "1.23" )
int
&long
long cents = new Double( 1.23d * 100 ).longValue() ;
cents
oumills
.)Money money = Money.parse("USD 23.87") ;
Para todos os tipos de cálculos relacionados a dinheiro, seria descuidado não usar
BigDecimal
. Por favor, useBigDecimal
para todos os seus cálculos.O que acontece se você não fizer isso? A precisão imprecisa de
double
/Double
pode levar a resultados simplesmente errados ao realizar qualquer tipo de operação matemática. Resultados errados podem custar dinheiro, credibilidade e tempo à sua empresa para corrigir cálculos errados.O desempenho provavelmente não será um problema. Resolva problemas de desempenho apenas quando eles surgirem e não faça pré-otimização para um problema que não existe.
BigDecimal: Use para todos os cálculos financeiros (faturamento, pagamentos, folha de pagamento, contabilidade) onde a precisão é crítica.
Razões:
Duplo: Use para cálculos não financeiros, processamento de dados em grande escala e seções críticas de desempenho onde uma leve perda de precisão é aceitável.
A chave aqui é usar BigDecimal quando os números afetam diretamente os resultados financeiros e Double ao trabalhar com grandes conjuntos de dados onde o desempenho é crítico e uma leve perda de precisão é tolerável.