Problemas com BigDecimal

Fala aí galera. To precisando de uma ajuda no seguinte:

Na minha base de dados tenho um registro com os seguintes valores

1 11/01/2010 3,357042030000000120

Se referindo a um índice financeiro.

Decidi optar por usar o BigDecimal quando consulto a base devido grande número de casa decimais.

Porém, quando chamo o método ResultSet.getBigDecimal(), passando o nome da coluna, ele está retornando apenas 3,35704203

Verifiquei a precisão com o método ResultSet.getBigDecimal().precision() e está retornando 9. Creio que este seja o motivo de estar sumindo com o restante do índice.

Alguém conhece uma forma de setar essa precisão ou como trabalhar neste contexto sem perda de dados?

ME AJUDE AÍ GALERA.

É o correto mesmo usar BigDecimal devido a sua precisão para tratar “moedas”. Como está definido esse campo no banco ?
Segundo o javadoc, o ResultSet retorna o BigDecimal com “full precision”.

Antes de mais nada, qual é o banco de dados ? Driver ?

Qual é o tipo do campo no banco de dados ?

Banco de dados: Oracle

Campo

INDICE NUMBER(31,20)

[quote=Victor Almeida]Banco de dados: Oracle

Campo

INDICE NUMBER(31,20)
[/quote]

Não podes informar que é um DECIMAL ?

[/quote]

Não podes informar que é um DECIMAL ?[/quote]

Não entendi JWizard.

[quote=Victor Almeida]

Não podes informar que é um DECIMAL ?

Não entendi JWizard.[/quote]

O formato que tu criou é um number e tu pega como um bigdecimal, acredito que isso esteja gerando seu problema de casas decimais.
Pergunto se tens como alterar o tipo no banco de dados, de number para um decimal.

[quote=nel][quote=Victor Almeida]

Não podes informar que é um DECIMAL ?

Não entendi JWizard.[/quote]

O formato que tu criou é um number e tu pega como um bigdecimal, acredito que isso esteja gerando seu problema de casas decimais.
Pergunto se tens como alterar o tipo no banco de dados, de number para um decimal.[/quote]

Galera, consegui fazer com o me retornasse o valor base de dados da seguinte forma:

indiceFinanceiroVO.setCotacaoIndice(new BigDecimal(rs.getDouble("valor_ref"), new MathContext(18)));

Porém, estou tendo outra dificuldade.

Para valores como este: 0,871159999999999934 o BigDecimal está fazendo um arredondamento implícito e transformando o número em:

0.871160000000000045

Existe alguma forma de desabilitar estes arredondamentos automáticos?

O tipo double tem precisão de 15 algarismos - não converta diretamente um double em um BigDecimal a menos que saiba o que está fazendo.

[quote=Victor Almeida][quote=nel][quote=Victor Almeida]

Não podes informar que é um DECIMAL ?

Não entendi JWizard.[/quote]

O formato que tu criou é um number e tu pega como um bigdecimal, acredito que isso esteja gerando seu problema de casas decimais.
Pergunto se tens como alterar o tipo no banco de dados, de number para um decimal.[/quote]

Galera, consegui fazer com o me retornasse o valor base de dados da seguinte forma:

indiceFinanceiroVO.setCotacaoIndice(new BigDecimal(rs.getDouble("valor_ref"), new MathContext(18)));

Porém, estou tendo outra dificuldade.

Para valores como este: 0,871159999999999934 o BigDecimal está fazendo um arredondamento implícito e transformando o número em:

0.871160000000000045

Existe alguma forma de desabilitar estes arredondamentos automáticos?
[/quote]

Vou repetir: não pode alterar o tipo na base de dados para Decimal ? Como o entanglement disse, o double tem precisão de 15 algarismos, o que é inferior ao oferecido por um BigDecimal.

E qual a melhor forma de trabalhar com números com muitas casas decimais?

[quote=nel][quote=Victor Almeida][quote=nel][quote=Victor Almeida]

Não podes informar que é um DECIMAL ?

Não entendi JWizard.[/quote]

O formato que tu criou é um number e tu pega como um bigdecimal, acredito que isso esteja gerando seu problema de casas decimais.
Pergunto se tens como alterar o tipo no banco de dados, de number para um decimal.[/quote]

Galera, consegui fazer com o me retornasse o valor base de dados da seguinte forma:

indiceFinanceiroVO.setCotacaoIndice(new BigDecimal(rs.getDouble("valor_ref"), new MathContext(18)));

Porém, estou tendo outra dificuldade.

Para valores como este: 0,871159999999999934 o BigDecimal está fazendo um arredondamento implícito e transformando o número em:

0.871160000000000045

Existe alguma forma de desabilitar estes arredondamentos automáticos?
[/quote]

Vou repetir: não pode alterar o tipo na base de dados para Decimal ? Como o entanglement disse, o double tem precisão de 15 algarismos, o que é inferior ao oferecido por um BigDecimal.[/quote]

JWizard, infelizmente o banco de dados foi projetado desta forma e não tenho como mudar. Existe outra alternativa?

Dica: o que rs.getString (em vez de rs.getBigDecimal) retorna?

Se for uma string como “3.357042030000000120” (ponto decimal) você pode passar ao construtor de BigDecimal diretamente.

Se for uma string como “3,357042030000000120” (vírgula decimal) você pode usar um DecimalFormat, setando corretamente os DecimalFormatSymbols, e lembrando que você tem também de acertar o DecimalFormat para que parse retorne um BigDecimal (setParseBigDecimal (true)).

Eu não sei exatamente o motivo dessa diferença. Mas o construtor do BigDecimal que recebe double tenta inferir os dígitos do número decimal usando operações de deslocamento de bits para encontrar cada dígito. Eu não sei se a diferença é um bug ou se é uma limitação do algoritmo em si, mas um jeito mais seguro de fazer essa conversão é usar o métod BigDecimal.valueOf(). Nesse caso, ele converte o double para String e constrói o BigDecimal a partir do String.

De qualquer maneira, trazer o resultado do banco de dados como double pode causar perda de precisão, que você não consegue recuperar novamente com o BigDecimal.

[quote=entanglement]Dica: o que rs.getString (em vez de rs.getBigDecimal) retorna?

Se for uma string como “3.357042030000000120” (ponto decimal) você pode passar ao construtor de BigDecimal diretamente.

Se for uma string como “3,357042030000000120” (vírgula decimal) você pode usar um DecimalFormat, setando corretamente os DecimalFormatSymbols, e lembrando que você tem também de acertar o DecimalFormat para que parse retorne um BigDecimal (setParseBigDecimal (true)).
[/quote]

Já tentei pensar neste caminho (rs.getString), porém, o meu retorno também está arredondando.

Por exemplo:
0,871159999999999934

retorna:
0.87116

Você já leu este artigo ???

What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Talvez ajude a entender algo mais!

Tem certeza mesmo que o erro é na leitura do banco de dados???

Um campo NUMBER (30, 20) deveria ser lido corretamente com um getBigDecimal. Se você usar alguma ferramenta da Oracle que visualize essa tabela, ele mostra corretamente esses dígitos?