Artículos de Tecnología > Programación

Redondeo de números en Java

mario-alvial
mario-alvial

En un sistema desarrollado para el área de telemarketing de una empresa, se encontró un error al mostrar el promedio de notas de los asistentes. Tenemos la siguiente tabla de notas para mostrar visualmente el problema:

Empleado: MarceloNota: 7,3213832
Empleado: YuriNota: 6.18317113
Empleado: MárioNota: 9,3181

Ten en cuenta que en esta tabla todos los valores están quebrados, con varios decimales. Sin embargo, para presentar las notas a los empleados, debemos simplificar este valor para que se vea mejor.

Para corregir este error, primero veamos el método que calcula y devuelve el promedio:

public static double calculaPromedio(Usuario usuario) {  

double total = 0.0;  

for (Double nota : usuario.getNotas()) {   

total += nota;  

}  

return total / usuario.getNotas().size();

}

Realmente, el promedio no tiene cuidado con el redondeo. El double resultante tendrá el número de cifras decimales que se acerque más al resultado verdadero de la operación matemática, respetando el límite de cifras decimales del tipo primitivo double.

El primer paso para solucionar este problema es crear un método que se encargue exclusivamente de redondear el valor calculado por el método calculaPromedio(). Entonces, incluso sin haber creado este método, lo devolveremos en calculaPromedio (). De esa forma:

public static double calculaPromedio(Usuario usuario) {  

double total = 0.0;  

for (Double nota : usuario.getNotas()) {   

total += nota;  

}  

return redondear(total / usuario.getNotas().size());

}

Creando la función de redondeo

Ya di spoiler de cómo será nuestro método, recibe como parámetro un double que es el resultado de calculaPromedio y devuelve un double también, que es el resultado de calculaPromedio() redondeado. Así que comencemos a crear este método:

private static double redondear(double promedio) {
}

Para redondear nuestro double, podemos usar el método estático round() de clase Math:

private static double redondear(double promedio) {  
return Math.round(promedio);
}

Tomando como ejemplo un empleado que tenía las siguientes notas: 4,0, 3,7 y 7,8, representados por este código:

public static void main(String[] args) {  
Usuario usuario = new Usuario();  
usuario.getNotas().add(4.0);  
usuario.getNotas().add(3.7);  
usuario.getNotas().add(7.8);  
System.out.println(calculaPromedio(usuario));
}

Su promedio, en la calculadora, sería: 5,166666667. Veamos el resultado que nos trae nuestro método:

https://www.alura.com.br/artigos/assets/uploads/2017/12/image_0-2.png

Ya es una mejora, porque al menos no tenemos esa infinidad de decimales. Pero, el valor real sería 5,166666667 y obtuvimos 5. Entonces no es muy preciso, ¿verdad?

Esto se debe a que el método round() devuelve el long más cercano al valor real dado en el parámetro. En nuestro caso, tenemos aproximadamente el valor real de 5,2. Por lo tanto, el long más cercano es 5.

Olvidando el 5 que obtuvimos volveremos a intentar con las mismas notas que usamos en el ejemplo anterior, pero primero mejoraremos nuestro método.

Para mejorar este redondeo, podemos utilizar una solución alternativa. Pensando que el método round() redondea a la longmás cerca, podemos multiplicar el promedio por 100, use el round() y luego dividir por 100. Haciendo esto en el código, tenemos:

private static double redondear(double promedio) {  
return Math.round(promedio * 100.0)/100.0;
}

Ejecutando el código, nuestro resultado es:

https://www.alura.com.br/artigos/assets/uploads/2017/12/image_1-2.png

Entendamos lo que pasó. Primero tomamos nuestro promedio que en nuestro caso tiene un valor de 5,166666667 y lo multiplicamos por 100. Con eso obtuvimos 516,6666667, luego usamos el round() que redondeó al long más cercano, 517, y finalmente dividimos 517 entre 100, obteniendo 5,17.

Está bien, ¿verdad? Probemos ahora con otros valores. Las notas del empleado ahora serán: 3,1, 4,3 y 2,5. El resultado teóricamente sería 3,30. Vamos a ver:https://www.alura.com.br/artigos/assets/uploads/2017/12/image_2-2.png

Date cuenta de que nuestro resultado es correcto, pero solo tiene un decimal. Este es el problema con el método que estamos usando para redondear, no podemos predecir cuántos lugares decimales tendrá el resultado.

¿Qué sería ideal? Idealmente, todos los promedios deberían tener exactamente dos lugares decimales. Para ayudarnos a hacer esto, podemos usar la clase DecimalFormat. Esta clase nos ayuda a formatear números para que se muestren correctamente.

Redondeo con DecimalFormat

Para empezar, creemos una instancia:

DecimalFormat df = new DecimalFormat("0.00");

"0.00" ¿Qué es eso que pones?

Entendamos. Cada 0 significa que el dígito correspondiente a ese decimal se mostrará con 0 o no. El siguiente paso es pensar en cómo se redondeará nuestro método. Para esto usaremos el método setRoundingMode ():

df.setRoundingMode(RoundingMode.HALF_UP);

En esta línea estamos diciendo que redondearemos de la mitad a la parte superior, es decir, si el promedio es 3,625, será 3,63.

Por fin, formateemos nuestro promedio usando el método format() y ya devuelve este valor. De esa forma:

private static String redondear(double promedio) {  
DecimalFormat df = new DecimalFormat("0.00");  df.setRoundingMode(RoundingMode.HALF_UP);  
return df.format(promedio);
}

Tenga en cuenta que al hacer esto recibimos un error de compilación. Esto sucedió porque nuestro método redondear() espera devolver un double, pero el método format() devuelve un String. ¿Y ahora?

Si nos detenemos a pensar, incluso tiene sentido devolver un String, porque ya hemos realizado todas las operaciones matemáticas que necesitamos hacer. Ahora solo necesitamos devolver el valor formateado para que lo vea el usuario. Por lo tanto, como ya no necesitaremos operar sobre el promedio, devolver lo mismo como String tiene sentido.]

Pero ¿no podríamos simplemente convertir esta String en un double y devolver este valor?

Sí, podemos, pero corremos el riesgo de perder el formateo realizado, por lo que optaremos por realmente devolver una String. Entonces, cambiemos nuestros métodos para que devuelva String.

Conclusión

Listo, formateamos los datos correctamente. El redondeo a veces es una tarea complicada, dependiendo de la situación necesitamos valores extremadamente precisos, como trabajar con dinero.

Para manejar dinero lo más adecuado es utilizar la clase BigDecimal que tiene una alta precisión.Para comprender mejor cómo es trabajar con redondeo y especialmente cuando se trata de dinero, tenemos el cursos de Java en Alura.

Puedes leer también:

Artículos de Tecnología > Programación

En Alura encontrarás variados cursos sobre Programación. ¡Comienza ahora!

Precios en:
USD
  • USD
  • BOB
  • CLP
  • COP
  • USD
  • PEN
  • MXN
  • UYU

Semestral

  • 272 cursos

    Cursos de Programación, Front End, Data Science, Innovación y Gestión.

  • Videos y actividades 100% en Español
  • Certificado de participación
  • Estudia las 24 horas, los 7 días de la semana
  • Foro y comunidad exclusiva para resolver tus dudas
  • Luri, la inteligencia artificial de Alura

    Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana

  • Acceso a todo el contenido de la plataforma por 6 meses
US$ 65.90
un solo pago de US$ 65.90
¡QUIERO EMPEZAR A ESTUDIAR!

Paga en moneda local en los siguientes países

Anual

  • 272 cursos

    Cursos de Programación, Front End, Data Science, Innovación y Gestión.

  • Videos y actividades 100% en Español
  • Certificado de participación
  • Estudia las 24 horas, los 7 días de la semana
  • Foro y comunidad exclusiva para resolver tus dudas
  • Luri, la inteligencia artificial de Alura

    Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana

  • Acceso a todo el contenido de la plataforma por 12 meses
US$ 99.90
un solo pago de US$ 99.90
¡QUIERO EMPEZAR A ESTUDIAR!

Paga en moneda local en los siguientes países

Acceso a todos
los cursos

Estudia las 24 horas,
dónde y cuándo quieras

Nuevos cursos
cada semana