Truncamento de double

Distintos senhores,

existe uma maneira mais elegante de truncar um double? Veja bem, quero truncar 2 casas decimais, e não arredondar. Exemplo:

1 / 3 = 0.3333333333…
truncando esse valor com 2 cadas decimais ficaria: 0.33

Encontrei duas “soluções” na web, mas as duas têm erro.

Primeira:

double d = 12.345;
DecimalFormat df = new DecimalFormat("#.##");
System.out.println(df.format(d));

Essa solução possui um erro, tentem colocar o valor de d para d = (4d/3d)*2;, eu esperava 2.66, mas ele me retorna 2.67.

A segunda solução que encontrei é pior, não funciona bem quando o número passado termina com zero:

public static double truncate(double x)
{
    long y=(long)(x*100);
    return (double)y/100;
}

Como workaround fiz a seguinte gambiarra (mas tem funcionado muito bem):

	public static double truncate(double d, int p) {
		String str = Double.toString(d);
		str = str.substring(0, str.indexOf(".")+p+1);
		return Double.parseDouble(str);
	}

Alguém sugere algo melhor? Ou seja, sem utilizar Strings no meio do caminho?

Olha fiz aqui rapidamente um método que faz isso usando um modelo matemático, faz o que pretendes na perfeição:

import java.lang.Math.*;

public class truncatura {

public static double truncar(double d, int casas_decimais) 

{

int var1 = (int) d;   // Remove a parte decimal do número... 2.3777 fica 2
double var2 = var1*Math.pow(10,casas_decimais); // adiciona zeros..2.0 fica 200.0
double var3 = (d - var1)*Math.pow(10,casas_decimais); /** Primeiro retira a parte decimal fazendo 2.3777 - 2 ..fica 0.3777, depois multiplica por 10^(casas decimais)
por exemplo se o número de casas decimais que queres considerar for 2, então fica 0.3777*10^2 = 37.77 **/
int var4 = (int) var3; // Remove a parte decimal da var3, ficando 37
int var5 = (int) var2; // Só para não haver erros de precisão: 200.0 passa a 200
int resultado = var5+var4; // O resultado será 200+37 = 237
double resultado_final = resultado/Math.pow(10,casas_decimais); // Finalmente divide-se o resultado pelo número de casas decimais, 237/100 = 2.37
return resultado_final; // Retorna o resultado_final :P 
}

public static void main(String []args) {
	//[Testing]
	double real = 2.3777;
	double truncado = truncar(real,2);
	
	System.out.println(truncado); 
   //[/testing] :)
}


}

Espero ter sido útil :slight_smile:

	double d = 12.345;  
	DecimalFormat dc = new DecimalFormat("#.##");  
	dc.setMinimumFractionDigits(2);
	dc.setMaximumFractionDigits(2);
	
	System.out.println(dc.format(d));

Pessoal,

obrigado pelas respostas… MAS!

Resposta para o SrFabio: coloque o número 2.530… o resultado que retorna é 2.52!!!

Resposta para andreix: double d = (4d / 3d) * 2; me retorna 2.67!!

Pois é, conversando com um colega de trabalho ele me falou que se fizermos 2.53 * 100 a JVM retorna 252.99999999999…

Como se sabe, alguns números não podem ser representados na base binária.

Bom, por enquanto vai ficar assim. Como estou trabalhando com moedas, a melhor representação é mesmo por String.

Obrigado a todos!

Amigo,

Uma solução para resolver a precisão do primitivo double é usar a classe java.math.BigDecimal. Ela não sofre perda de precisão. Veja a sua API:

http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html

Clovandi,
O negócio é usar bigdecimal mesmo:
BigDecimal x = new BigDecimal(0+2+2.69,MathContext.DECIMAL32).setScale(2);//4,69
System.out.println(x);
out:
4.69
Fonte: http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html
[]'s