Como posso truncar um double para apenas duas casas decimais em Java?

93

Por exemplo, tenho a variável 3.545555555, que gostaria de truncar para apenas 3,54.

Johnny
fonte
18
Esta NÃO é uma duplicata. Truncar e arredondar são duas coisas completamente diferentes.
markthegrea
Concordo, não sei por que isso está sinalizado como duplicado.
Bassinator

Respostas:

144

Se você quiser isso para fins de exibição, use java.text.DecimalFormat:

 new DecimalFormat("#.##").format(dblVar);

Se você precisar dele para cálculos, use java.lang.Math:

 Math.floor(value * 100) / 100;
Bozho
fonte
50
Isso não exibirá 3,545555555 truncado para 3,54, mas arredondado para 3,55. DecimalFormat.setRoundingMode () precisa ser definido como RoundingMode.FLOOR;
Christian García
9
isso não funciona para mim Math.floor (9,62 * 100) / 100 dá 9,61
Mani
4
Usar floorpara truncar funciona apenas para valores positivos.
Dev
3
@CristianGarcía O truncamento é feito corretamente, RoundingMode.DOWNcomo RoudingMode.FLOORsempre, em volta do infinito negativo.
Dev
46
DecimalFormat df = new DecimalFormat(fmt);
df.setRoundingMode(RoundingMode.DOWN);
s = df.format(d);

Verifique disponíveis RoundingModee DecimalFormat.

Cedric Dubourg
fonte
Não aborda a questão, que pedia truncamento em vez de arredondamento.
Basil Bourque
8
@BasilBourque RoundingMode.DOWN é truncamento. Compare com outras respostas que recomendam incorretamente funções de piso (piso apenas trunca números positivos), isso funciona corretamente para valores positivos e negativos.
Dev
1
@Dev eu estou corrigido. Vejo agora que DOWNisso realmente tem o efeito de truncamento para números positivos e negativos. Conforme visto na tabela de exemplos do documento .
Basil Bourque
23

Fórum pouco antigo, nenhuma das respostas acima funcionou para valores positivos e negativos (quero dizer para o cálculo e apenas para fazer truncar sem arredondamento). Do link Como arredondar um número para n casas decimais em Java

private static BigDecimal truncateDecimal(double x,int numberofDecimals)
{
    if ( x > 0) {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_FLOOR);
    } else {
        return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_CEILING);
    }
}

Este método funcionou bem para mim.

System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));

Resultados :

0.00
9.62
9.62
9.62
9.62
9.99
-9.99
-9.00
Mani
fonte
essa é a resposta mais escalonável para mais casos de teste
diego matos - keke
retornar novo BigDecimal (x) .setScale (numberofDecimals, RoundingMode.DOWN) .doubleValue ();
Shimon Doodkin
parece arredondado para baixo é como você quis dizer: docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html
Shimon Doodkin
9

Observe primeiro que a doubleé uma fração binária e realmente não tem casas decimais.

Se precisar de casas decimais, use a BigDecimal, que tem um setScale()método para truncamento, ou use DecimalFormatpara obter a String.

Michael Borgwardt
fonte
7

Se, por qualquer motivo, você não quiser usar um, BigDecimalpode transmitir seu doublepara umint para truncá-lo.

Se você deseja truncar o Ones lugar:

  • simplesmente lançar para int

Para o lugar Décimo :

  • multiplique por dez
  • lançar para int
  • lançado de volta para double
  • e divida por dez.

centésimos lugar

  • multiplique e divida por 100 etc.

Exemplo:

static double truncateTo( double unroundedNumber, int decimalPlaces ){
    int truncatedNumberInt = (int)( unroundedNumber * Math.pow( 10, decimalPlaces ) );
    double truncatedNumber = (double)( truncatedNumberInt / Math.pow( 10, decimalPlaces ) );
    return truncatedNumber;
}

Neste exemplo, decimalPlacesseria o número de casas APÓS as unidades que você deseja ir, então 1 arredondaria para a décima casa , 2 para as centésimas , e assim por diante (0 arredondaria para a casa das unidades e um negativo para as dezenas , etc.)

Tarvis
fonte
3
Esta é uma solução geral terrível . Tanto a multiplicação quanto o elenco acabarão descartando dados e resultando em números efetivamente aleatórios se unroundedNumberforem grandes o suficiente. Pode funcionar para o exemplo em questão, mas uma solução geral deve funcionar para qualquer um double.
blm
4

A formatação como uma string e a conversão de volta para o dobro, acho que lhe dará o resultado desejado.

O valor duplo não será redondo (), piso () ou teto ().

Uma solução rápida para isso poderia ser:

 String sValue = (String) String.format("%.2f", oldValue);
 Double newValue = Double.parseDouble(sValue);

Você pode usar o sValue para fins de exibição ou o newValue para cálculos.

Jao Assy
fonte
1
Ele arredonda para mim o valor mais próximo. Por exemplo: 0,018 é convertido em 0,02 quando eu fiz isso.
karan patel
3

Talvez Math.floor(value * 100) / 100? Esteja ciente de que os valores como 3.54podem não ser representados exatamente com um double.

Vlad
fonte
3

Você pode usar o objeto NumberFormat Class para realizar a tarefa.

// Creating number format object to set 2 places after decimal point
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);            
nf.setGroupingUsed(false);

System.out.println(nf.format(precision));// Assuming precision is a double type variable
Rushdi Shams
fonte
3

3,545555555 para obter 3,54. Tente seguir para isso:

    DecimalFormat df = new DecimalFormat("#.##");

    df.setRoundingMode(RoundingMode.FLOOR);

    double result = new Double(df.format(3.545555555);

Isso dará = 3,54!

Ankush G
fonte
1

Aqui está o método que uso:

double a=3.545555555; // just assigning your decimal to a variable
a=a*100;              // this sets a to 354.555555
a=Math.floor(a);      // this sets a to 354
a=a/100;              // this sets a to 3.54 and thus removing all your 5's

Isso também pode ser feito:

a=Math.floor(a*100) / 100;
Mitchell Hynes
fonte
0

Talvez seguindo:

double roundTwoDecimals(double d) { 
      DecimalFormat twoDForm = new DecimalFormat("#.##"); 
      return Double.valueOf(twoDForm.format(d));
}  
Ritesh Mengji
fonte
Veja as outras respostas. Você não pode fazer isso de forma confiável se a resposta for representada em ponto flutuante.
Marquês de Lorne,
0

Uma verificação rápida é usar o método Math.floor. Criei um método para verificar duas vezes ou menos casas decimais abaixo:

public boolean checkTwoDecimalPlaces(double valueToCheck) {

    // Get two decimal value of input valueToCheck 
    double twoDecimalValue = Math.floor(valueToCheck * 100) / 100;

    // Return true if the twoDecimalValue is the same as valueToCheck else return false
    return twoDecimalValue == valueToCheck;
}
chris31389
fonte
-1

Eu tenho uma versão ligeiramente modificada do Mani .

private static BigDecimal truncateDecimal(final double x, final int numberofDecimals) {
    return new BigDecimal(String.valueOf(x)).setScale(numberofDecimals, BigDecimal.ROUND_DOWN);
}

public static void main(String[] args) {
    System.out.println(truncateDecimal(0, 2));
    System.out.println(truncateDecimal(9.62, 2));
    System.out.println(truncateDecimal(9.621, 2));
    System.out.println(truncateDecimal(9.629, 2));
    System.out.println(truncateDecimal(9.625, 2));
    System.out.println(truncateDecimal(9.999, 2));
    System.out.println(truncateDecimal(3.545555555, 2));

    System.out.println(truncateDecimal(9.0, 2));
    System.out.println(truncateDecimal(-9.62, 2));
    System.out.println(truncateDecimal(-9.621, 2));
    System.out.println(truncateDecimal(-9.629, 2));
    System.out.println(truncateDecimal(-9.625, 2));
    System.out.println(truncateDecimal(-9.999, 2));
    System.out.println(truncateDecimal(-9.0, 2));
    System.out.println(truncateDecimal(-3.545555555, 2));

}

Resultado:

0.00
9.62
9.62
9.62
9.62
9.99
9.00
3.54
-9.62
-9.62
-9.62
-9.62
-9.99
-9.00
-3.54
HolyLance
fonte
-2

Isso funcionou para mim:

double input = 104.8695412  //For example

long roundedInt = Math.round(input * 100);
double result = (double) roundedInt/100;

//result == 104.87

Eu pessoalmente gosto desta versão porque ela realmente executa o arredondamento numericamente, ao invés de convertê-la em uma String (ou similar) e então formatá-la.

Rainbow975
fonte
1
A pergunta original é sobre truncamento, não arredondamento. Além disso, converter um duplo em um longo não funcionará bem se o duplo for grande o suficiente.
blm
-2
//if double_v is 3.545555555
String string_v= String.valueOf(double_v);
int pointer_pos = average.indexOf('.');//we find the position of '.'
string_v.substring(0, pointer_pos+2));// in this way we get the double with only 2 decimal in string form
double_v = Double.valueOf(string_v);//well this is the final result

bem, isso pode ser um pouco estranho, mas acho que pode resolver o seu problema :)

user5251903
fonte
Este código faz o trabalho, mas não é elegante e tem baixo desempenho. Pode ser bom em projetos escolares, mas definitivamente não é uma solução que alguém usaria na produção de qualquer sistema, a menos que você queira ter dores de cabeça mais tarde.
cbaldan