R$ Números grandes

Olá pessoal,

Estou precisando realizar contas bastante grandes, onde os resultados vao ultrapassar a casa dos trilhoes de reais, estava indo td bem, eu estava usando inicialmente double, mais logo percebi que ele nao aguenta, na verdade até aguenta, mas ele comeca a calcular em hexadecimal… Então comecei a usar o BigDecimal, ele funciona, mas quando eu fui testar, atribui o valor 999999999999999.99 (999 trilhões…), a um objeto do tipo BigDecimal, ele arrendondou para 1000000000000000.00 (1 quadrilhão…), entao eu comecei a testar para ver qual era o valor máximo que um objeto BigDecimal suporta sem dar pau, e cheguei a conclusao, que o valor máximo é 69999999999999.99 (69 trilhoes…), a partir dos 70999999999999.99 (70 trilhoes…) ele comeca a alterar os valores que eu digitei, tipo esse de 70 trilhoes fica com 1 centavo a menos, 70999999999999.98, o que não pode ocorrer de jeito nenhum, já o numero 200999999999999.99 (200 trilhoes…) fica assim quando atribuido a um BigDecimal 201000000000000.00, completamente errado, mais um exemplo 310999999999999.99 no objeto BigDecimal fica 311000000000000.00.

Esse é o codigo que to usando BigDecimal z = new BigDecimal(310999999999999.99).setScale(2, BigDecimal.ROUND_HALF_UP);

Quero dizer também que ja tentei usar todos os tipos de arrendondamento no método setScale. inclusive o ROUND_UNNECESSARY, que eu achava que deveria fazer com que o numero nao fosse arrendodado, porém nao mudou em nada, os numeros continuaram sendo arrendodados.
Também ja pensei em criar uma classe para isso, usando um long para os reais e outro long para os centavos, mais dai eu teria que praticamente reeinventar td, desde a soma até os calculos mais complexos…
Também ja pesquisei bastante na internet, ja vi varios tópicos sobre o assunto aqui no guj e em outros sites tbem, porém nao consegui achar solução…

É incrivel como mesmo usando o ROUND_UNNECESSARY, ele continua atribuindo um centavo a mais ou a menos nos valores a partir de 70999999999999.99.

Gostaria de saber a opinião de vcs, se alguem já passou por isso, se resolveu e como resolveu, se largou pros ursos, hehhe, enfim, se alguem tem alguma ideia pra eu poder calcular sem problemas valores em moeda real, que ultrapassem a casa dos trilhoes e sem esses centavos a mais ou a menos…

Desde ja, agradecido !!!

Não sei como vc está construindo seus BigDecimals, fiz um teste aqui e não tive problema.

BigDecimal bd1 = new BigDecimal( "299999999999999999999999999.9999999999999999999999999999999999", MathContext.UNLIMITED ); BigDecimal bd2 = new BigDecimal( "299999999999999999999999999.9999999999999999999999999999999999", MathContext.UNLIMITED ); System.out.println( bd1.add( bd2 ) );

Mesmo sem usar o MathContext o resultado continua o mesmo.

Até mais!

Olá davidbuzatto,

Valeu a dica, agora funcionou !!

A grande diferença entre nossos codigos, é que eu nao estava passando uma String para o construtor do BigDecimal, como vc pode ver no 1º post.

Assim é usando o seu codigo…

BigDecimal bd1 = new BigDecimal( "999999999999999.99", MathContext.UNLIMITED );

e assim é usando o meu

BigDecimal z = new BigDecimal(999999999999999.99).setScale(2, BigDecimal.ROUND_HALF_UP);

Dai quando coloquei o valor entre aspas como no seu codigo, funcionou certinho, porém vou passar a utilizar a classe MathContext, como no seu codigo, achei que fica mais facil na leitura e utilização do codigo. O problema era que eu estava passando um numero ao inves de uma string. pelo menos essa era a unica grande diferença entre os 2 codigos, e quando coloquei entre aspas funcionou certinho.

Muito obrigado !!, té a próxima…

Agora sim entendi. Não tinha postado porque realmente não fazia sentido o ocorrido.

O BigDecimal tem vários construtores, entre eles um que recebe String e outro que recebe double. Passando como literal, ele provavelmente estava identificando-o como um double, causando a perda de precisão derivada da IEEE-754.

Até!

Era isso mesmo que estava acontecendo maquiavelbona, eu só estava usando o construtor errado…

valeu a ajuda ai rapaziada !!! t+

Acho que tem a ver com

BigDecimal.ROUND_HALF_UP

ROUND_HALF_UP se refere a arredondamento… ele devia estar arredondando seu valor. Acho que não tem nada a ver com o fato de passar double ou string…