[RESOLVIDO] Truncar double

Boa Tarde,

Ontem precisei truncar um valor double e passei uma tarde toda pesquisando e quebrando a cabeça. Acredito ter encontrado uma solução muito simples que vou deixar aqui para o caso de alguém precisar um dia.

Só uma coisa a acrescentar é que quando precisar de precisão é melhor utilizar a classe BigDecimal do que o double. Os tipos primitivos não são tão rigorosos na parte de precisão (carece de fontes hehehe).

Até mais.

Links sobre os métodos de arredondamento:
http://docs.oracle.com/javase/1.5.0/docs/api/java/math/RoundingMode.html#HALF_UP
http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#ROUND_DOWN

import java.math.BigDecimal;

/*
 * O pulo do gato é saber que "truncar" é arrendondar para baixo, então usei o método de arredondamento BigDecimal.ROUND_DOWN.
 */

public class Truncar {

	public double truncate(Double valor, int precisao) {
		BigDecimal bd = BigDecimal.valueOf(valor);
		bd = bd.setScale(precisao, BigDecimal.ROUND_DOWN);

		return bd.doubleValue();
	}

	public static void main(String[] args) {

		Truncar t = new Truncar();

		double d = 12.53346867565d;
		System.out.println(d);
		System.out.println(t.truncate(d, 4));

	}
}

E o que houve com o bom e velho:
a) Multiplicar o valor por 10^precisao;
b) Fazer o cast do valor para int (ou long, se vc usa valores grandes);
c) Dividir o valor por 10^precisao.

Eu ia falar nisso - aliás, é melhor usar Math.ceil, Math.floor ou Math.rint (dependendo do que se quer fazer, arredondar para cima, truncar para baixo ou então arredondar usando a regra dos banqueiros) que fazer o tal cast para long ou int. Se não me engano, as três operações costumam ser mais rápidas que fazer o cast e reconverter para double :slight_smile:

[quote=entanglement]Eu ia falar nisso - aliás, é melhor usar Math.ceil, Math.floor ou Math.rint (dependendo do que se quer fazer, arredondar para cima, truncar para baixo ou então arredondar usando a regra dos banqueiros) que fazer o tal cast para long ou int. Se não me engano, as três operações costumam ser mais rápidas que fazer o cast e reconverter para double :slight_smile:
[/quote]

Com certeza.
Eu só citei o algoritmo padrão da faculdade®.

O custo de um cast de double para int pode chegar a mais de 80 ciclos de CPU. Contra 1 do ceil.
Inclusive, no meu pipeline gráfico, arranjei uma função em C++ que faz a mesma coisa com menos ciclos (e um pouco menos de precisão também). Para mais informações sobre o truque desse cast fantasticamente rápido: http://stereopsis.com/sree/fpu2006.html