Pergunta

Eu entendo que BigDecimal é recomendado melhores práticas para representar valores monetários em Java. O que você usa? Existe uma biblioteca melhor que você prefere usar em vez disso?

Foi útil?

Solução

BigDecimal todo o caminho. Já ouvi falar de algumas pessoas criando suas próprias Cash ou Money classes que encapsulam um valor em dinheiro com a moeda, mas sob a pele ainda é um BigDecimal, provavelmente com BigDecimal.ROUND_HALF_EVEN arredondamento.

Editar: Como Don menciona em sua resposta , há projetos de código aberto como timeandmoney , e enquanto eu aplaudo-los para tentar impedir que os desenvolvedores de ter reinventar a roda, eu simplesmente não tenho bastante confiança em uma biblioteca pré-alfa para usá-lo em um ambiente de produção. Além disso, se você cavar em torno sob o capô, você verá eles usam BigDecimal também .

Outras dicas

Pode ser útil para pessoas que chegam aqui pelos motores de busca para saber sobre JodaMoney: http: // www .joda.org / joda-dinheiro / .

Eu não estou expressando minha opinião aqui, mas existem muito bons argumentos contra BigDecimal que alguém provavelmente deveria jogar fora:

http://lemnik.wordpress.com/2011 / 03/25 / BigDecimal-e-seu-dinheiro /

Uma biblioteca conveniente que eu corri em mais cedo é o biblioteca Joda-Money . Uma de suas implementações é realmente baseado em BigDecimal. Ele baseia-se na ISO-4217 especificação para moedas e pode suportar uma lista personalizada moeda (carregado via CVS).

Esta biblioteca tem um pequeno número de arquivos que pode rapidamente passar se são necessárias modificações. Joda-Money é publicado sob a licença Apache 2.0.

Se você estiver usando apenas dólares e centavos, eu usaria um longo (compensado por 2 casas decimais). Se precisar de mais detalhes, grande decimal pode ser o caminho a percorrer.

De qualquer maneira, eu provavelmente estender a classe para ter um .toString () que utiliza o formato correto, e como um lugar para colocar outros métodos que possam surgir (Por um longo, multiplicar e dividir vão awry se decimal não é ajustado)

Além disso, se você usar definir sua própria classe e interface, então você pode substituir a implementação à vontade.

BigDecimal ou outra representação de ponto fixo é o que é geralmente necessária para o dinheiro.

ponto flutuante (Double, Float) representações e cálculos são inexatos, levando a resultados errados.

Você tem que ser tão cuidadosos quando se trata de tempo e dinheiro.

Quando você está trabalhando com o dinheiro, espero que todo mundo deve saber nunca usar uma bóia ou um duplo.

Mas estou inseguro sobre BigDecimal.

Na maioria dos casos você vai ficar bem se você apenas manter o controle de centavos em um int ou longo. Desta forma, você nunca lidar com uma casa decimal.

Você só exibir dólares quando você imprimi-lo. Sempre trabalho com centavos usando inteiros internos. Isto pode ser complicado se necessidade de dividir ou necessidade de usar Math.abs ().

No entanto, você pode cuidar metade capaz um centavo, ou mesmo um centésimo de centavo. Eu não sei o que é uma boa maneira de fazer isso. Você só precisa de lidar com milésimo de centavos e usar um longo. Ou talvez você será forçado a usar BigDecimal

Gostaria de fazer muito mais lendo sobre isso, mas ignorar todo mundo que começa a falar sobre como usar um float ou double para representar dinheiro. Eles estão apenas pedindo para ter problemas.

Eu sinto o meu conselho não está completa, por isso, colocar mais embora para ele. Você está lidando com tipos perigosos!

A criação de uma classe de dinheiro é o caminho a percorrer. Usando BigDecimal por baixo (ou até mesmo um int). Em seguida, usando a classe de moeda para definir o arredondamento convenção.

Infelizmente, sem sobrecarga de operador Java torna bastante desagradável criar tais tipos básicos.

Há uma biblioteca melhor, timeandmoney . IMO, é muito superior às bibliotecas fornecidos pelo JDK para representar estes 2 conceitos.

Definitivamente não BigDecimal. Há tantas regras especiais para arredondamento e apresentação que você tem que se preocupar.

Martin Fowler recomenda a implementação de uma classe dinheiro dedicado para representar valores monetários, e que também regras implementos para conversão de moeda.

Ei, aqui está um artigo muito interessante sobre BigDecimal, e um exemplo ilustrativo de por que às vezes é usado em vez de duplas. BigDecimal Tutorial .

Você pode usar a classe DecimalFormat quando última instância exibindo um valor de moeda. Ele fornece suporte de localização e é muito extensível.

Eu encapsular BigDecimal na classe Dinheiro que também tem uma moeda apenas como alguém mencionado acima. O importante é que você faça uma quantidade extrema de testes de unidade e especialmente se trabalhar com diferentes moedas. Também é uma boa idéia se você adicionar um construtor conveniente que leva uma corda ou um método de fábrica que faz o mesmo para que você possa escrever seus testes algo como isto:

   assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));

Há sempre limitações e especificidades envolvidas. Qualquer pessoa sem experiência suficiente para apreciar as questões sutis descritas no seguinte artigo deve reconsiderar seriamente antes de lidar com dados financeiros do mundo real:

http://lemnik.wordpress.com/2011/ 25/03 / BigDecimal-e-seu-dinheiro

BigDecimal não é a única representação correta ou a única peça do quebra-cabeça. Dadas certas condições, usando uma classe Dinheiro apoiado por centavos armazenados como um inteiro poderia ser suficiente e seria muito mais rápido do que BigDecimal. Sim, isso implica o uso de dólares como moeda e limites de valores, mas tais restrições são perfeitamente aceitável para muitos casos de uso e todas as moedas têm casos especiais para arredondamento e sub-denominações de qualquer maneira, então não há nenhuma solução "universal".

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