domingo, abril 22, 2012

Redondear un número sin usar estructura If...else

Durante el curso que ofrece Stanford en la página Udacity, "Building a search engine" tenía que hacer un pequeño programa que redondeara un número dejando 0 espacios decimales.
Por ejemplo:
El número 3.289 debería redondearlo a 3.
El 74.701 debería redondearlo a 75.
El 5.5 debería redondearlo a 6.

Bueno, la única forma que se me ocurrió era evaluar el número después del punto decimal y pasarlo por una condición como "si el número es mayor o igual a 5 entonces incrementa el número en 1", luego convertir el número a string para poder solamente extraer los caracteres antes del punto decimal. Pero, el problema es que, aunque la solución es perfectamente válida, se suponía que debía de hacerse solamente con lo que había visto del curso, y hasta ese momento no habíamos visto la estructura if...else.

Así sería como quería en Java:
public static double redondearConIf(double numero){
  String aux = numero + "";
  int punto = aux.indexOf('.');
  double numeroRedondeado = 0.0;
  if(aux.charAt(punto + 1) >= 5){
   aux = aux.substring(0,punto);
  }
  else{
   numero += 1;
   aux = numero + "";
   aux =  aux.substring(0,punto);
  }
  try{
   numeroRedondeado = Double.parseDouble(aux);
  }catch(NumberFormatException nfex){
   nfex.printStackTrace();
  }
  return numeroRedondeado;

 } 

En Python:
def redondear(numero):
    puntoDecimal = str(numero).find('.')
    if(int(str(numero)[puntoDecimal+1])  > = 5):
        numero = numero + 1
        return str(numero)[:puntoDecimal]
    else:
        return str(numero)[:puntoDecimal]

print redondear(3.593)

Pero yo por algún sesgo cognitivo o porque ya conocía dicha estructura, se me hizo difícil encontrar otra solución, por lo que tuve que mirar la solución y me sorprendí con lo sencillo y elegante que es. Veamos.

En Java:
public static double redondear(double numero){
  numero = numero + 0.5;
  String aux = numero + "";
  int punto = aux.indexOf('.');
  aux = aux.substring(0,punto);
  double numeroRedondeado = 0;
  try{
   numeroRedondeado = Double.parseDouble(aux);
  }catch(NumberFormatException nfex){
   nfex.printStackTrace();
  }
  return numeroRedondeado;
 }

En Python:
numero = numero + 0.5
    punto_decimal = str(numero).find('.')
    return int(str(numero)[:punto_decimal])

print redondear(33.293)

Como vemos, el "truco" de la solución elegante es que no nos preocupamos por saber cual es la cifra después del punto. Simplemente incrementamos el número en 0.5 y automáticamente si la cifra después del punto era igual o mayor a 5 el número incrementará, de lo contrario no lo hará. Y ya solo tenemos que tomar los números antes del punto, lo cual lo hacemos en Java con la instrucción: aux.substring(0,punto);. Y en Python con la sentencia: str(numero)[:punto_decimal]. Además esta forma es un poquitín más eficiente, pero no muy significante.

No hay comentarios:

Publicar un comentario

¿Qué opinas?