Dentre todos os tipos de aplicações criadas todos os dias por vários desenvolvedores ao longo do mundo, um deles certamente é extremamente usado, importante e movimenta mercados de muito valor: aplicações financeiras. Esses tipos de aplicações, ou até mesmo outras que façam uso dos recursos de finanças, são muito comuns no mercado e extremamente importantes para definir os rumos de circulação do dinheiro.

Paralelo a isso, os desenvolvedores de sistemas das mais diversas tecnologias e linguagens de programação tem de lidar com valores e precisões cada vez maiores e bem definidas quando do desenvolvimento de um sistema desse tipo. O arredondamento de valores decimais se faz presente, por exemplo, nos sistemas de postos de gasolina, onde o preço chega a ser exibido com até 5 casas decimais de valor. Essa precisão, se relacionada a sistemas que manipulam muito dinheiro pode significar perdas ou ganhos muito altos.

Na linguagem de programação Java existem inúmeras maneiras de lidar com isso. Algumas mais precisas, outras mais complexas, mas uma dúvida sempre paira na cabeça de muitos programadores quando lhe é perguntado sobre esse tipo de operação: Como arredondar números em Java? Qual a melhor maneira de fazer isso para a realidade do sistema que se está a desenvolver?

As respostas quase sempre ficam no primeiro link encontrado na pesquisa do Google, mas nem sempre isso pode significar a melhor estratégia para a sua realidade, para a sua aplicação. Veja neste artigo algumas maneiras de se trabalhar arredondando valores decimais em Java, analisando variáveis como tipos de dados, performance, dentre outras.

java.Math

A classe java.lang.Math é uma classe que existe dentro do pacote principal do Java, aquele que não necessita imports para ser usado. Essa classe dispõe de alguns métodos que lidam diretamente com essa funcionalidade de arredondamento. Veja alguns deles:

Math.round()

Esse método, tido como o método padrão para arredondar valores nesta classe, é usado para receber um parâmetro decimal (Double ou float) e retornar o valor arredondado em inteiro. Talvez esse seja o maior problema desses métodos, eles retornam um inteiro. E para o caso do posto de gasolina isso não se aplicaria, uma vez que é necessário fazer os respectivos arredondamentos a um nível de casas decimais também. Além disso, o método também retorna o valor arredondando-o para o valor mais alto (considere também os negativos no mesmo conceito, ou seja, mais alto = mais próximo de zero). Veja na Listagem 1 um exemplo de uso do mesmo:


System.out.println(Math.round(10.5));
// Imprime 11
Listagem 1. Uso do método round()

Math.ceil()

Este método é muito semelhante ao método round(), entretanto a diferença consiste que o mesmo retorna um decimal (Double) ao invés de um inteiro. Portanto, o número recebido será arredondado para o valor mais próximo e alto e retornado como um decimal da mesma forma. Confira na Listagem 2 o que acontece com o mesmo exemplo da Listagem 1.


System.out.println(Math.ceil(-10.5));
// Imprime -10.0
Listagem 2. Uso do método ceil()

Math.floor()

Este método é semelhante ao floor() no conceito de casas decimais, entretanto ele retornará o valor baseando-se no menor e mais próximo. Usando o mesmo exemplo até então, só que negativo para ter um controle maior do menor. Veja a Listagem 3.


System.out.println(Math.floor(10.5));
// Imprime 10.0
Listagem 3. Uso do método floor()

Os recursos da classe Math são os mais usados. Mas como deu para perceber, são limitados e não tem uma precisão e formatação muito desenvolvidas.

DecimalFormat

A classe DecimalFormat, como o próprio nome sugere, é uma classe que foi criada com a finalidade de formatar valores decimais. Ela se baseia em padrões estabelecidos para determinar como os mesmos valores serão formatados. Por exemplo, suponha que você deseje formatar um número decimal com cinco casas decimais de precisão, tal como foi definido anteriormente nas limitações da classe Math; então você poderia formatar o mesmo valor através do código da Listagem 4.


DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
// Imprime 0,91238
Listagem 4. Uso da classe DecimalFormat para formatação de valores decimais

Uma observação que deve ser feita é que o método format() em questão retorna uma String formatada no padrão informado.

Além disso, notem que o valor não veio arredondado para cima. Isso acontece porque ela só manipula valores de casas de decimais com modo de arredondamento para baixo. Se mudar o padrão, e adicionar o RoundingMode como na Listagem 5, verá que o resultado muda e o arredondamento acontece:


DecimalFormat df = new DecimalFormat("###.######");
df.setRoundingMode(RoundingMode.UP);
System.out.println(df.format(0.53583332));
// Imprime 0,535834
Listagem 5. Mudando padrão de formatação

BigDecimal

Outra classe bem famosa para fazer esse tipo de operação é a classe BigDecimal. Essa classe é amplamente usada para manipular valores decimais de precisão alta, como em variáveis que guardarão valores monetários, por exemplo.

Particularmente, essa classe constitui uma das melhores formas de se trabalhar com decimais e suas casas decimais, mesmo que os valores não sejam tão altos assim. Na Listagem 6 é exibida uma demonstração de como a classe trabalha:


double d = 12.548795;
BigDecimal bd = new BigDecimal(d).setScale(3, RoundingMode.HALF_EVEN);
System.out.println(bd.doubleValue());
// Imprime 12.549
Listagem 6. Uso da classe BigDecimal para formatar os valores decimais

A criação do novo BigDecimal em conjunto com o uso do método setScale() faz com que a formatação se dê de forma eficaz. O parâmetro de valor “3” passado para este método indica o número de casas decimais a serem consideradas e o segundo parâmetro (HALF_EVEN) indica que o arredondamento sempre deve acontecer para o valor mais próximo, cima ou baixo. Finalmente, o valor pode ser impresso através da chamada ao método doubleValue() que retorna uma variável cópia do tipo double com o valor formatado.

Concluindo

Esses são apenas alguns dos recursos mais usados na linguagem para esse tipo de funcionalidade. Se procurar na internet, é possível encontrar inúmeras outras formas, usando regex, formatação de Strings ou métodos próprios de formatação. No mais, fica a lacuna de você decidir qual melhor se enquadra e usar. Até mais.