JAXB, BIGDECIMAL ou DUPLE?
-
25-09-2019 - |
Pergunta
Trabalho em diferentes serviços da Web e sempre uso o WSDL primeiro.
Jaxb gera para um tipo como:
<xsd:simpleType name="CurrencyFormatTyp">
<xsd:restriction base="xsd:decimal">
<xsd:totalDigits value="13"/>
<xsd:fractionDigits value="2"/>
<xsd:minInclusive value="0.01"/>
</xsd:restriction>
</xsd:simpleType>
um tipo de ligação a java BigDecimal
(como é mencionado na especificação JAXB).
Quando eu faço uma operação aritmética simples com valores do tipo double
(que são armazenados em um banco de dados e mapeados via Hibernate para o Tipo Double) Eu tenho problemas.
<ns5:charge>0.200000000000000011102230246251565404236316680908203125</ns5:charge>
<ns5:addcharge>0.0360000000000000042188474935755948536098003387451171875</ns5:addcharge>
<ns5:tax>0.047199999999999998900879205621095024980604648590087890625</ns5:tax>
<ns5:totalextax>0.2360000000000000153210777398271602578461170196533203125</ns5:totalextax>
Qual seria o caminho certo?
- Converter todos os meus valores em duplo (Jaxb Ligation de
BigDecimal
paradouble
) - Mapeamento de hibernato
double
paraBigdecimal
e faça todas as minhas operações aritméticas em um tipo de objeto.
Solução
Você nunca quer usar ponto flutuante formatos (como double
e float
em Java) para operações de moeda, porque elas têm precisão limitada e foram projetadas para manter valores que de alguma forma são derivados da medição (nesse caso, eles não são absolutamente precisos, para começar, nesse caso, a precisão limitada é menos um problema ).
O que todo cientista da computação deve saber sobre aritmética de ponto flutuante é a artigo sobre o tópico. É um pouco pesado em matemática, mas realmente ajuda a entender isso (alternativamente, o artigo vinculado por Michael Borgwardt é Muito de mais fácil de entender e ainda demonstra/explica o problema).
Para evitar esse tipo de problema, certifique -se de usar BigDecimal
exclusivamente em seu código e que todos os pontos de armazenamento/transferência externos também usam valores de ponto fixo/precisão arbitrária (ou seja, seu banco de dados também não deve armazenar números de ponto flutuante).
Outras dicas
- Leia o Guia de ponto flutuante
- Nunca usar
double
oufloat
Para valores em dinheiro - Usar
BigDecimal
Em vez disso, é exatamente para isso