Cómo redondear un número an posiciones decimales en Java

1301
Alex Spurling 2008-10-01 06:01.

Lo que me gustaría es un método para convertir un doble en una cadena que se redondea usando el método de la mitad hacia arriba, es decir, si el decimal a redondear es 5, siempre se redondea al siguiente número. Este es el método estándar de redondeo que la mayoría de la gente espera en la mayoría de las situaciones.

También me gustaría que solo se mostraran dígitos significativos, es decir, no debería haber ceros al final.

Sé que un método para hacer esto es usar el String.formatmétodo:

String.format("%.5g%n", 0.912385);

devoluciones:

0.91239

lo cual es genial, sin embargo, siempre muestra números con 5 lugares decimales incluso si no son significativos:

String.format("%.5g%n", 0.912300);

devoluciones:

0.91230

Otro método es utilizar DecimalFormatter:

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

devoluciones:

0.91238

Sin embargo, como puede ver, esto usa un redondeo medio par. Es decir, se redondeará hacia abajo si el dígito anterior es par. Lo que me gustaría es esto:

0.912385 -> 0.91239
0.912300 -> 0.9123

¿Cuál es la mejor manera de lograr esto en Java?

30 answers

786
curtisk 2008-10-01 06:14.

Use setRoundingMode, configure RoundingModeexplícitamente para manejar su problema con la ronda media-par, luego use el patrón de formato para su salida requerida.

Ejemplo:

DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
    Double d = n.doubleValue();
    System.out.println(df.format(d));
}

da la salida:

12
123.1235
0.23
0.1
2341234.2125

EDITAR : La respuesta original no aborda la precisión de los valores dobles. Eso está bien si no le importa mucho si se redondea hacia arriba o hacia abajo. Pero si desea un redondeo preciso, debe tener en cuenta la precisión esperada de los valores. Los valores de coma flotante tienen una representación binaria internamente. Eso significa que un valor como 2.7735 no tiene ese valor exacto internamente. Puede ser un poco más grande o un poco más pequeño. Si el valor interno es ligeramente menor, no se redondeará a 2,7740. Para remediar esa situación, debe ser consciente de la precisión de los valores con los que está trabajando y sumar o restar ese valor antes de redondear. Por ejemplo, cuando sepa que sus valores tienen una precisión de hasta 6 dígitos, entonces, para redondear los valores intermedios hacia arriba, agregue esa precisión al valor:

Double d = n.doubleValue() + 1e-6;

Para redondear, reste la precisión.

480
asterite 2008-10-01 06:07.

Suponiendo que valuees a double, puede hacer:

(double)Math.round(value * 100000d) / 100000d

Eso es para precisión de 5 dígitos. El número de ceros indica el número de decimales.

193
MetroidFan2002 2008-10-01 08:33.
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

te conseguirá un BigDecimal. Para obtener la cadena fuera de él, simplemente llamar a eso BigDecimal's toStringmétodo o el toPlainStringmétodo para Java 5+ para una cadena sin formato.

Programa de muestra:

package trials;
import java.math.BigDecimal;

public class Trials {

    public static void main(String[] args) {
        int yourScale = 10;
        System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
    }
118
Milhous 2008-10-01 06:58.

También puede utilizar el

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

para asegurarse de tener los ceros al final.

88
Marquis of Lorne 2012-10-02 17:18.

Como han señalado otros, la respuesta correcta es utilizar DecimalFormato BigDecimal. El punto flotante no tiene lugares decimales, por lo que no es posible redondear / truncar a un número específico de ellos en primer lugar. Tienes que trabajar en base decimal, y eso es lo que hacen esas dos clases.

Estoy publicando el siguiente código como contraejemplo de todas las respuestas en este hilo y, de hecho, en todo StackOverflow (y en otros lugares) que recomiendan la multiplicación seguida de truncamiento seguido de división. Incumbe a los defensores de esta técnica explicar por qué el siguiente código produce un resultado incorrecto en más del 92% de los casos.

public class RoundingCounterExample
{

    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }

    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

Salida de este programa:

10001 trials 9251 errors

EDITAR: Para abordar algunos comentarios a continuación, rehice la parte del módulo del bucle de prueba usando BigDecimaly new MathContext(16)para la operación del módulo de la siguiente manera:

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

Resultado:

10001 trials 4401 errors
85
user593581 2011-01-28 23:52.

Suponga que tiene

double d = 9232.129394d;

puedes usar BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

o sin BigDecimal

d = Math.round(d*100)/100.0d;

con ambas soluciones d == 9232.13

61
JibW 2011-09-29 21:01.

Puede utilizar la clase DecimalFormat.

double d = 3.76628729;

DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));
39
Ovesh 2009-09-02 01:14.

Real's Java How-to publica esta solución, que también es compatible con versiones anteriores a Java 1.6.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();

ACTUALIZACIÓN: BigDecimal.ROUND_HALF_UP está en desuso - Use RoundingMode

BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();
33
Chris Cudmore 2008-10-01 06:09.
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
31
Ivan 2011-07-04 05:50.

@Milhous: el formato decimal para redondear es excelente:

También puede utilizar el

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

para asegurarse de tener los ceros al final.

Agregaría que este método es muy bueno para proporcionar un mecanismo de redondeo numérico real, no solo visualmente, sino también durante el procesamiento.

Hipotético: debe implementar un mecanismo de redondeo en un programa GUI. Para alterar la exactitud / precisión de la salida de un resultado, simplemente cambie el formato de intercalación (es decir, dentro de los corchetes). Así que eso:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

volvería como salida: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

volvería como salida: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

volvería como salida: 0.9124

[EDITAR: también si el formato de intercalación es así ("# 0. ############") e ingresa un decimal, por ejemplo, 3.1415926, por el bien del argumento, DecimalFormat no produce ninguna basura ( por ejemplo, ceros finales) y devolverá: 3.1415926.. si así lo desea. Por supuesto, es un poco detallado para el gusto de algunos desarrolladores, pero oye, tiene poca memoria durante el procesamiento y es muy fácil de implementar].

Básicamente, la belleza de DecimalFormat es que maneja simultáneamente la apariencia de la cuerda, así como el nivel de precisión de redondeo establecido. Ergo: obtiene dos beneficios por el precio de una implementación de código. ;)

20
Mifeet 2015-08-16 05:09.

Aquí hay un resumen de lo que puede usar si desea el resultado como Cadena:

  1. DecimalFormat # setRoundingMode () :

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  2. BigDecimal # setScale ()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

Aquí hay una sugerencia de qué bibliotecas puede usar si lo desea doublecomo resultado. Sin embargo, no lo recomendaría para la conversión de cadenas, ya que es posible que double no pueda representar exactamente lo que desea (consulte, por ejemplo, aquí ):

  1. Precisión de Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Funciones de Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. Utilidades de Weka

    double rounded = Utils.roundDouble(0.912385, 5)
    
19
Amit 2011-04-28 05:56.

Puede utilizar el siguiente método de utilidad:

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}
13
MAbraham1 2017-07-28 03:36.

Una solución sucinta:

   public static double round(double value, int precision) {
      int scale = (int) Math.pow(10, precision);
      return (double) Math.round(value * scale) / scale;
  }

Ver también, https://stackoverflow.com/a/22186845/212950Gracias a jpdymond por ofrecer esto.

9
Easwaramoorthy K 2014-07-22 23:49.

Puedes usar BigDecimal

BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);

Referir: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/

7
Li Ying 2014-02-20 19:04.

Pruebe esto: org.apache.commons.math3.util.Precision.round (doble x, escala int)

Ver: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html

La página de inicio de Apache Commons Mathematics Library es: http://commons.apache.org/proper/commons-math/index.html

La implementación interna de este método es:

public static double round(double x, int scale) {
    return round(x, scale, BigDecimal.ROUND_HALF_UP);
}

public static double round(double x, int scale, int roundingMethod) {
    try {
        return (new BigDecimal
               (Double.toString(x))
               .setScale(scale, roundingMethod))
               .doubleValue();
    } catch (NumberFormatException ex) {
        if (Double.isInfinite(x)) {
            return x;
        } else {
            return Double.NaN;
        }
    }
}
7
Andrei Lupsa 2016-11-10 21:50.

Como no encontré una respuesta completa sobre este tema, armé una clase que debería manejar esto correctamente, con soporte para:

  • Formateo : formatee fácilmente un doble a una cadena con un cierto número de posiciones decimales
  • Análisis : analiza el valor formateado para volverlo a duplicar
  • Configuración regional : formatee y analice utilizando la configuración regional predeterminada
  • Notación exponencial : comience a usar la notación exponencial después de un cierto umbral

El uso es bastante simple :

(Por el bien de este ejemplo, estoy usando una configuración regional personalizada)

public static final int DECIMAL_PLACES = 2;

NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);

String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"

double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

Aquí está la clase :

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;

public class NumberFormatter {

    private static final String SYMBOL_INFINITE           = "\u221e";
    private static final char   SYMBOL_MINUS              = '-';
    private static final char   SYMBOL_ZERO               = '0';
    private static final int    DECIMAL_LEADING_GROUPS    = 10;
    private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
    private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation

    private DecimalFormat decimalFormat;
    private DecimalFormat decimalFormatLong;
    private DecimalFormat exponentialFormat;

    private char groupSeparator;

    public NumberFormatter(int decimalPlaces) {
        configureDecimalPlaces(decimalPlaces);
    }

    public void configureDecimalPlaces(int decimalPlaces) {
        if (decimalPlaces <= 0) {
            throw new IllegalArgumentException("Invalid decimal places");
        }

        DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
        separators.setMinusSign(SYMBOL_MINUS);
        separators.setZeroDigit(SYMBOL_ZERO);

        groupSeparator = separators.getGroupingSeparator();

        StringBuilder decimal = new StringBuilder();
        StringBuilder exponential = new StringBuilder("0.");

        for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
            decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
        }

        for (int i = 0; i < decimalPlaces; i++) {
            decimal.append("#");
            exponential.append("0");
        }

        exponential.append("E0");

        decimalFormat = new DecimalFormat(decimal.toString(), separators);
        decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
        exponentialFormat = new DecimalFormat(exponential.toString(), separators);

        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
        exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
    }

    public String format(double value) {
        String result;
        if (Double.isNaN(value)) {
            result = "";
        } else if (Double.isInfinite(value)) {
            result = String.valueOf(SYMBOL_INFINITE);
        } else {
            double absValue = Math.abs(value);
            if (absValue >= 1) {
                if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
                    value = Math.floor(value);
                    result = exponentialFormat.format(value);
                } else {
                    result = decimalFormat.format(value);
                }
            } else if (absValue < 1 && absValue > 0) {
                if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
                    result = decimalFormat.format(value);
                    if (result.equalsIgnoreCase("0")) {
                        result = decimalFormatLong.format(value);
                    }
                } else {
                    result = exponentialFormat.format(value);
                }
            } else {
                result = "0";
            }
        }
        return result;
    }

    public String formatWithoutGroupSeparators(double value) {
        return removeGroupSeparators(format(value));
    }

    public double parse(String value, double defValue) {
        try {
            return decimalFormat.parse(value).doubleValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defValue;
    }

    private String removeGroupSeparators(String number) {
        return number.replace(String.valueOf(groupSeparator), "");
    }

}
7
Ivan 2011-07-04 23:10.

Si realmente desea números decimales para el cálculo (y no solo para la salida), no use un formato de punto flotante basado en binario como double.

Use BigDecimal or any other decimal-based format.

Utilizo BigDecimal para los cálculos, pero tenga en cuenta que depende del tamaño de los números con los que esté tratando. En la mayoría de mis implementaciones, encuentro que analizar de doble o entero a Long es suficiente para cálculos de números muy grandes.

De hecho, recientemente usé parsed-to-Long para obtener representaciones precisas (a diferencia de los resultados hexadecimales) en una GUI para números tan grandes como ################### ############### caracteres (como ejemplo).

6
Jorgesys 2018-03-15 07:40.

Para lograr esto podemos usar este formateador:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

o:

DecimalFormat df = new DecimalFormat("0.00"); :

Utilice este método para obtener siempre dos decimales:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Definiendo estos valores:

91.32
5.22
11.5
1.2
2.6

Usando el método podemos obtener estos resultados:

91.32
5.22
11.50
1.20
2.60

demostración en línea.

5
ashr 2016-03-04 01:43.

Por si acaso alguien todavía necesita ayuda con esto. Esta solución me funciona perfectamente.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();

}

devuelve a String con la salida deseada.

4
marco 2015-11-06 02:54.

Estoy de acuerdo con la respuesta elegida para usar DecimalFormat--- o alternativamente BigDecimal.

¡Lea primero la Actualización a continuación!

Sin embargo, si no desea redondear el valor doble y obtener un doubleresultado de valor, se puede utilizar org.apache.commons.math3.util.Precision.round(..)como se mencionó anteriormente. La implementación usa BigDecimal, es lenta y genera basura.

La DoubleRounderutilidad en la biblioteca decimal4j proporciona un método similar pero rápido y sin basura :

 double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

Saldrá

 0.667
 0.666
 1000.0
 9.00800700601E10

Ver https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

Descargo de responsabilidad: estoy involucrado en el proyecto decimal4j.

Actualización: como señaló @iaforek, DoubleRounder a veces arroja resultados contradictorios. La razón es que realiza un redondeo matemáticamente correcto. Por ejemplo DoubleRounder.round(256.025d, 2), se redondeará hacia abajo a 256.02 porque el valor doble representado como 256.025d es algo más pequeño que el valor racional 256.025 y, por lo tanto, se redondeará hacia abajo.

Notas:

  • Este comportamiento es muy similar al del BigDecimal(double)constructor (pero no al valueOf(double)que usa el constructor de cadenas).
  • El problema se puede eludir primero con un paso de redondeo doble a una mayor precisión, pero es complicado y no voy a entrar en detalles aquí.

Por esas razones y todo lo mencionado anteriormente en esta publicación, no puedo recomendar el uso de DoubleRounder .

3
Jasdeep Singh 2011-09-09 01:09.

El siguiente fragmento de código muestra cómo mostrar n dígitos. El truco consiste en establecer la variable pp en 1 seguida de n ceros. En el siguiente ejemplo, el valor de pp variable tiene 5 ceros, por lo que se mostrarán 5 dígitos.

double pp = 10000;

double myVal = 22.268699999999967;
String needVal = "22.2687";

double i = (5.0/pp);

String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();
3
Drew Noakes 2015-06-29 01:54.

Si está utilizando DecimalFormatpara convertir doublea String, es muy sencillo:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);

double num = 1.234567;
return formatter.format(num);

Hay varios RoundingModevalores de enumeración para seleccionar, según el comportamiento que requiera.

3
Suragch 2017-02-21 04:42.

Vine aquí solo queriendo una respuesta simple sobre cómo redondear un número. Esta es una respuesta complementaria para proporcionar eso.

Cómo redondear un número en Java

El caso más común es usar Math.round().

Math.round(3.7) // 4

Los números se redondean al número entero más cercano. Un .5valor se redondea. Si necesita un comportamiento de redondeo diferente, puede usar una de las otras funciones matemáticas . Vea la comparación a continuación.

redondo

Como se indicó anteriormente, esto se redondea al número entero más cercano. .5los decimales se redondean. Este método devuelve un int.

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4

Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

hacer techo

Cualquier valor decimal se redondea al siguiente entero. Va al techo . Este método devuelve un double.

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0

Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

suelo

Cualquier valor decimal se redondea al siguiente entero. Este método devuelve un double.

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0

Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

rint

Esto es similar a redondear en que los valores decimales redondean al entero más cercano. Sin embargo, a diferencia de round, los .5valores se redondean al número entero par. Este método devuelve un double.

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***

Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***
3
Craigo 2018-01-07 21:10.

Si está utilizando una tecnología que tiene un JDK mínimo. Aquí hay una forma sin bibliotecas de Java:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;
2
Se Song 2016-11-25 23:06.

DecimalFormat es la mejor forma de generar resultados, pero no lo prefiero. Siempre hago esto todo el tiempo, porque devuelve el valor doble. Entonces puedo usarlo más que solo salida.

Math.round(selfEvaluate*100000d.0)/100000d.0;

O

Math.round(selfEvaluate*100000d.0)*0.00000d1;

Si necesita un valor de lugares decimales grandes, puede usar BigDecimal en su lugar. De todos modos .0es importante. Sin él, el redondeo de 0.33333d5 devuelve 0.33333 y solo se permiten 9 dígitos. La segunda función sin .0tiene problemas con 0.30000 devuelve 0.30000000000000004.

2
Md. Jamal Uddin 2019-08-21 17:29.

aquí está mi respuesta:

double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(num));

System.out.println(num); // 4.89
2
Amr Ali 2018-02-14 00:37.

Aquí hay una función mejor que redondea los casos 1.005extremos como correctamente.

Simplemente, agregamos el valor flotante más pequeño posible (= 1 ulp; unidad en el último lugar) al número antes de redondear. Esto se mueve al siguiente valor representable después del número, alejándose de cero.

Este es un pequeño programa para probarlo: ideone.com

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
public static double round(double num, int digits) {

    // epsilon correction
    double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
    double p = Math.pow(10, digits);
    return Math.round(n * p) / p;
}

// test rounding of half
System.out.println(round(0.5, 0));   // 1
System.out.println(round(-0.5, 0));  // -1

// testing edge cases
System.out.println(round(1.005, 2));   // 1.01
System.out.println(round(2.175, 2));   // 2.18
System.out.println(round(5.015, 2));   // 5.02

System.out.println(round(-1.005, 2));  // -1.01
System.out.println(round(-2.175, 2));  // -2.18
System.out.println(round(-5.015, 2));  // -5.02
1
Alain Cruz 2019-10-26 10:07.

Entonces, después de leer la mayoría de las respuestas, me di cuenta de que la mayoría de ellas no serán precisas, de hecho, usar BigDecimalparece ser la mejor opción, pero si no comprende cómo RoundingModefunciona, inevitablemente perderá precisión. Descubrí esto cuando trabajaba con números grandes en un proyecto y pensé que podría ayudar a otros que tienen problemas para redondear números. Por ejemplo.

BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());

Esperaría obtener 1363.28como resultado, pero terminará con 1363.27, lo que no se espera, si no sabe lo que RoundingModeestá haciendo. Entonces, mirando en Oracle Docs , encontrará la siguiente descripción para RoundingMode.HALF_UP.

Modo de redondeo para redondear hacia el "vecino más cercano" a menos que ambos vecinos sean equidistantes, en cuyo caso redondee hacia arriba.

Entonces, sabiendo esto, nos dimos cuenta de que no obtendremos un redondeo exacto, a menos que queramos redondear hacia el vecino más cercano . Entonces, para lograr una ronda adecuada, necesitaríamos recorrer desde el n-1decimal hacia los dígitos decimales deseados. Por ejemplo.

private double round(double value, int places) throws IllegalArgumentException {

    if (places < 0) throw new IllegalArgumentException();

    // Cast the number to a String and then separate the decimals.
    String stringValue = Double.toString(value);
    String decimals = stringValue.split("\\.")[1];

    // Round all the way to the desired number.
    BigDecimal bd = new BigDecimal(stringValue);
    for (int i = decimals.length()-1; i >= places; i--) {
        bd = bd.setScale(i, RoundingMode.HALF_UP);
    }

    return bd.doubleValue();
}

Esto acabará dándonos el resultado esperado, que sería 1363.28.

1
Enamul Haque 2020-05-09 18:49.

He usado abajo como en Java 8. Me está funcionando

    double amount = 1000.431;        
    NumberFormat formatter = new DecimalFormat("##.00");
    String output = formatter.format(amount);
    System.out.println("output = " + output);

Producción:

output = 1000.43
0
aim 2014-04-22 13:51.

Donde dp = lugar decimal que desea, y el valor es un doble.

    double p = Math.pow(10d, dp);

    double result = Math.round(value * p)/p;

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Cuéntanos tus mejores trucos de Washington, DC

Cuéntanos tus mejores trucos de Washington, DC

Hemos pirateado algunas ciudades industriales en esta columna, como Los Ángeles y Las Vegas. Ahora es el momento de una ciudad militar-industrial-compleja.

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está eliminando su sección de tallas grandes y mezclando tallas más grandes con todo lo demás

Un minorista está enlatando su sección de tallas grandes. Pero no están tomando la categoría solo en línea o descontinuándola por completo.

La mejor forma de guardar animales de peluche es dentro de un puf

La mejor forma de guardar animales de peluche es dentro de un puf

Entiendo totalmente, completamente si tienes una relación difícil con los animales de peluche. Son lindos, tienen valor sentimental y es difícil separarse de ellos.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language