Problema com arredondamento

5 respostas
ibispo

Olá todos,

Eu tenho esse método abaixo para arredondar valores:

public static double arredondar( double valor, int casas, int ceilOrFloor) {
      double arredondado = valor;
      arredondado *= (Math.pow(10, casas) );

      if (ceilOrFloor == 0)
         arredondado = Math.ceil(arredondado);
      else
         arredondado = Math.floor(arredondado);

      arredondado /= (Math.pow(10, casas));

      return arredondado;
   }

Se eu executar o método

arredondar( 81.9156, 2, 0 );

ele retorna corretamente 81.92

Agora se eu executar com outro valor

arredondar( 81.9, 2, 0 );

ele retorna erroneamente 81.91

Gostaria de saber se existe alguma falha no metodo acima ou se alguem tem algum bom exemplo de metodo para arredondar valores double.

No aguardo de respostas,

Vlw.

5 Respostas

T

Isto aqui funciona.

import java.math.*;

class Arredondamento {

    /**
     * @param valor O valor a ser arredondado.
     * @param casas O número de casas.
     * @param useCeil true = Arredondar sempre para cima. false = truncar
     */
    public static double arredondar (String valor, int casas, boolean useCeil) {
        BigDecimal bd = new BigDecimal (valor);
        return bd.setScale (casas, useCeil ? RoundingMode.CEILING : RoundingMode.FLOOR).doubleValue();
    }
   public static void main(String[] args) {
       System.out.println (arredondar( "81.9156", 2, false ));
       System.out.println (arredondar( "81.9", 2, false ));
       System.out.println (arredondar( "81.9156", 2, true ));
       System.out.println (arredondar( "81.9", 2, true ));
   }
}
E

Ow entao vc pode usar as classes BigDecimal ou DecimalFormat para te auxiliar. Boa Sorte!

rsoliveira

Hi o/

Cara, coloquei um System.out.println após cada operação que fizestes com a variável arredondado e descobri que o problema ta lá em cima, no momento que tu faz essa operação:

arredondado *= (Math.pow(10, casas));

O resultado obtido é esse: 8190.000000000001

O problema é que eu não faço a mínima idéia do pq…Bug?

Vou continuar testando o/

T

rsoliveira:
Hi o/

Cara, coloquei um System.out.println após cada operação que fizestes com a variável arredondado e descobri que o problema ta lá em cima, no momento que tu faz essa operação:

arredondado *= (Math.pow(10, casas));

O resultado obtido é esse: 8190.000000000001

O problema é que eu não faço a mínima idéia do pq…Bug?

Vou continuar testando o/

Isso não é um bug e sim uma particularidade do ponto flutuante binário (double, float).
http://docs.sun.com/source/806-3568/ncg_goldberg.html

ibispo

rsoliveira:
Hi o/

Cara, coloquei um System.out.println após cada operação que fizestes com a variável arredondado e descobri que o problema ta lá em cima, no momento que tu faz essa operação:

arredondado *= (Math.pow(10, casas));

O resultado obtido é esse: 8190.000000000001

O problema é que eu não faço a mínima idéia do pq…Bug?

Vou continuar testando o/

Realmente foi isso que percebi quando printei no console do Netbeans esse resultado 8190.000000000001… coisa doisa.

Bem, mas a dica do colega thingol sobre a classe de Arredondamento, funcionou. O q achei estranho é receber o valor como string mas sem problemas. eu converto dentro do método e apliquei no meu projeto e funcionou perfeitamente. Segue abaixo:

public class Valores {

   public final static boolean ARRED_CIMA = true;
   public final static boolean ARRED_TRUNCA = false;

   public static double arredondar (double vl, int casas, boolean useCeil) {
       String valor = Double.toString(vl);
       BigDecimal bd = new BigDecimal (valor);
        return bd.setScale (casas, useCeil ? RoundingMode.CEILING : RoundingMode.FLOOR).doubleValue();
   }

}

Quando quero utilizar o metodo eu starto assim:

Valores.arredondar( 81.9156, 2, Valores.ARRED_CIMA );

Valeu todos!

Criado 3 de março de 2009
Ultima resposta 3 de mar. de 2009
Respostas 5
Participantes 4