¿Cómo puedo truncar un doble a solo dos lugares decimales en Java?

93

Por ejemplo, tengo la variable 3.545555555, que me gustaría truncar a solo 3.54.

Johnny
fuente
18
Esto NO es un duplicado. Truncar y redondear son dos cosas completamente diferentes.
markthegrea
De acuerdo, no sé por qué está marcado como duplicado.
Bassinator

Respuestas:

144

Si lo desea para fines de visualización, use java.text.DecimalFormat:

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

Si lo necesita para los cálculos, utilice java.lang.Math:

 Math.floor(value * 100) / 100;
Bozho
fuente
50
Esto no mostrará un 3,545555555 truncado a 3,54, sino que se redondeará a 3,55. DecimalFormat.setRoundingMode () debe establecerse en RoundingMode.FLOOR;
Christian García
9
esto no funciona para mí Math.floor (9.62 * 100) / 100 da 9.61
Mani
4
Usar floorpara truncar solo funciona para valores positivos.
Dev
3
@ ChristianGarcía El truncamiento está bien hecho con RoundingMode.DOWNcomo RoudingMode.FLOORsiempre vueltas hacia el infinito negativo.
Dev
46
DecimalFormat df = new DecimalFormat(fmt);
df.setRoundingMode(RoundingMode.DOWN);
s = df.format(d);

Consultar disponible RoundingModey DecimalFormat.

Cedric Dubourg
fuente
No aborda la Pregunta, que pedía truncamiento en lugar de redondeo.
Basil Bourque
8
@BasilBourque RoundingMode.DOWN es truncamiento. Compare con otras respuestas que recomiendan incorrectamente funciones de piso (el piso solo trunca los números positivos), esto funciona correctamente tanto para valores positivos como negativos.
Dev
1
@Dev Me corrijo. Ahora veo que de DOWNhecho tiene el efecto de truncamiento tanto para números positivos como negativos. Como se ve en la tabla de ejemplos en el doc .
Basil Bourque
23

Bit Old Forum, ninguna de las respuestas anteriores funcionó para valores positivos y negativos (me refiero al cálculo y solo para truncar sin redondeo). Desde el enlace Cómo redondear un número an decimales en 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 funcionó bien para mí.

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
fuente
esta es la respuesta más escalable para más casos de prueba
diego matos - keke
devolver nuevo BigDecimal (x) .setScale (numberofDecimals, RoundingMode.DOWN) .doubleValue ();
Shimon Doodkin
parece redondear hacia abajo es como lo que quisiste decir: docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html
Shimon Doodkin
9

Tenga en cuenta primero que a doublees una fracción binaria y en realidad no tiene decimales.

Si necesita lugares decimales, use a BigDecimal, que tiene un setScale()método de truncamiento, o use DecimalFormatpara obtener un String.

Michael Borgwardt
fuente
7

Si, por alguna razón, no desea utilizar a BigDecimal, puede convertir su doublea intpara truncarlo.

Si desea truncar al lugar de los unos :

  • simplemente lanzar a int

Al lugar de las Décimas :

  • multiplicar por diez
  • emitir a int
  • lanzar de nuevo a double
  • y dividir por diez.

Centésimas de lugar

  • multiplicar y dividir por 100, etc.

Ejemplo:

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;
}

En este ejemplo, decimalPlacessería el número de lugares DESPUÉS del lugar de las unidades al que desea ir, por lo que 1 redondearía al lugar de las décimas , 2 a las centésimas , y así sucesivamente (0 se redondea al lugar de las unidades y negativo uno a las decenas , etc.)

Tarvis
fuente
3
Esta es una terrible solución general. Tanto la multiplicación como el elenco terminarán tirando datos y darán como resultado lo que son efectivamente números aleatorios si unroundedNumberes lo suficientemente grande. Puede funcionar para el ejemplo de la pregunta, pero una solución general debería funcionar para cualquiera double.
blm
4

Formatear como una cadena y convertir de nuevo a doble creo que le dará el resultado que desea.

El valor doble no será round (), floor () o ceil ().

Una solución rápida podría ser:

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

Puede utilizar el sValue para fines de visualización o el newValue para el cálculo.

Jao Assy
fuente
1
Me redondea al valor más cercano. Por ejemplo: 0.018 se convierte en 0.02 cuando hice esto.
karan patel
3

Math.floor(value * 100) / 100¿ Quizás ? Tenga en cuenta que los valores como 3.54pueden no estar representados exactamente con un double.

Vlad
fuente
3

Puede utilizar el objeto de clase NumberFormat para realizar la tarea.

// 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
fuente
3

3.545555555 para obtener 3.54. Intente seguir para esto:

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

    df.setRoundingMode(RoundingMode.FLOOR);

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

¡Esto dará = 3,54!

Ankush G
fuente
1

Este es el método que utilizo:

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

Esto también se puede hacer:

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

Quizás siguiendo:

double roundTwoDecimals(double d) { 
      DecimalFormat twoDForm = new DecimalFormat("#.##"); 
      return Double.valueOf(twoDForm.format(d));
}  
Ritesh Mengji
fuente
Vea las otras respuestas. No puede hacerlo de manera confiable si la respuesta debe representarse en punto flotante.
Marqués de Lorne
0

Una comprobación rápida es utilizar el método Math.floor. Creé un método para verificar un doble para dos o menos lugares decimales a continuación:

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
fuente
-1

Tengo una versión ligeramente modificada de 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));

}

Salida:

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
fuente
-2

Esto funcionó para mí:

double input = 104.8695412  //For example

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

//result == 104.87

Personalmente, me gusta esta versión porque en realidad realiza el redondeo numérico, en lugar de convertirla en una cadena (o similar) y luego formatearla.

Arcoiris975
fuente
1
La pregunta original es sobre truncar, no redondear. Además, convertir un doble en largo no funcionará bien si el doble es lo suficientemente grande.
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

Bueno, esto puede ser un poco incómodo, pero creo que puede resolver tu problema :)

usuario5251903
fuente
Este código hace el trabajo, pero no es elegante y tiene un rendimiento deficiente. Puede que esté bien en proyectos escolares, pero definitivamente no es una solución que alguien usaría en producción para cualquier sistema, a menos que quieras tener dolores de cabeza más adelante.
cbaldan