Ya no se redondea como en los viejos tiempos

Hoy he asistido sorprendido a uno de esos momentos que hace que te explote la cabeza. Todo empezó con este tuit:

tuit1

Rápidamente me puse manos a la obra y lo probé en python, con la ventaja de que por las particularidades de este lenguaje siempre tengo instaladas dos versiones en los ordenadores que uso.

Capturapython

Así que en la versión 2.7 de Python vemos el redondeo “de toda la vida”, en el que el redondeo de 1.5 es 2 y el redondeo de 2.5 es 3. Pero si ejecutamos el mismo código para la versión 3.2 de Python tenemos que para ambos casos el resultado es 2.

¿El mundo se ha vuelto loco? Eso es lo primero que pensé, pero resulta que no, todo esto tiene su lógica. En pocos tuits se resolvió el misterio:

tuit2

tuit3

Y de paso se demostró que soy un empanado que no se había enterado de este cambio. El IEEE 754 es un estándar para el tratamiento de números en coma flotante, o hablando para no informáticos: para tratar números con decimales. Y en este estándar se recomienda, desde 2008, que el redondeo que se debe usar es Round half to even. 

Con este redondeo lo que se hace es el redondeo de toda la vida con una excepción para los números que tienen como decimal 0.5. Cuando la parte decimal es 0.5 lo que se hace es redondear al entero par más cercano al número. Por eso al redondear 2.5 lo que obtenemos es un 2 en lugar de un 3, ya que 2 es el número entero par más cercano a 2.5.

¿Por qué? Maldita sea ¡Por qué!

Después de mi sorpresa e ira inicial y de buscar un poco de información me di cuenta de que el asunto tenía mucha lógica. ¿Por qué un número que acaba en 0.5 debe ser redondeado al entero inmediatamente superior? Al fin y al cabo está a medio camino entre dos enteros, elegir el entero superior es simplemente un acuerdo al que hemos llegado los falibles humanos. Lo justo en este caso, sería que en la mitad de los casos el redondeo sea hacia arriba y en la otra mitad, el redondeo fuera hacia abajo. Y precisamente eso es lo que consigue este método.

Además el redondeo clásico provocaba un problema al tratar con números negativos:

Capturapythonnegativos

En el redondeo clásico de números con 0.5 como parte decimal en nuestros programas estábamos eligiendo el entero inmediatamente superior para números positivos y el inmediatamente inferior para números negativos (3 es mayor que 2.5 y -3 es menor que -2.5). Si lo pensamos fríamente, no parece demasiado correcto. Con el nuevo método los números negativos y positivos pueden ser redondeados a su entero inmediatamente superior o inferior.

[Añadido] Como bien apunta darth_suicune en los comentarios, el motivo de escoger este método es más profundo y afecta directamente al hecho de realizar cálculos una vez realizado el redondeo. En banca se lleva usando muchos años este redondeo y también se le denomina redondeo Gaussiano o estadístico. Pues bien, con este redondeo los cálculos posteriores al redondeo (y sobre todo medias) son más precisos que cuando se usa un redondeo estándar.

Así que ya sabéis, hemos redondeado por encima de nuestras posibilidades y ha llegado la troika de los estándares y nos ha dado un buen meneo. Lo único que este meneo nos lo dieron hace años y yo no me he enterado hasta ahora, empanado que es uno.

Así me siento hoy. (Fuente Wikipedia)

Así me siento hoy. (Fuente Wikipedia)

PD: Podéis comprobar en Wolfram Alpha que la cosa va en serio:

round25wa

Anuncios

Publicado el 14 marzo, 2014 en Divulgación y etiquetado en , , , . Guarda el enlace permanente. 12 comentarios.

  1. Toma ya, pues ni idea tenía. Y sí, claro. Tiene sentido aunque nos resulte raro.

  2. Pues yo no le veo la lógica, o redondeas siempre para arriba o redondeas siempre para abajo, ¿Por qué redondear siempre al par? Así en 20 decimales consecutivos 11 redondearan a par y 9 a impar dejando en desventaja a estos últimos (suponiendo, por ejemplo, un sorteo)

    • Pero si redondeas hacia arriba tendrás en los 20 casos que has sumado 0.5 a los valores, en el otro caso has sumado 0.5 y restado 0.5 en una relación 10-10. Si haces el proceso para una gran cantidad de números tus resultados estarán menos influenciados por haber tomado una decisión “fija” en el redondeo de los .5

      Imagínate que tienes números (positivos) con un solo decimal que tienes que redondear con el método clásico:

      .1, .2, .3, .4 irán al entero inmediatamente inferior
      .5, .6, .7, .8, .9 irán al entero inmediatamente superior

      Si la distribución de números es más o menos homogénea, estás obteniendo valores superiores en general porque los .5 van a ir siempre al entero superior. En cambio si aplicas el otro método, los pares irán al entero inferior y los impares al entero superior, no estás provocando valores más altos por el simple hecho del redondeo elegido, estás “repartiendo” los .5

      • En el entero inferior deberías incluir el .0
        el .5 siempre va al entero superior, sí, y por eso si tengo 2.5 irá a 3 y si tengo 3.5 irá a 4. Del modo este el 1.5 y el 2.5 va a 2 y el 3.5 y el 4.5 a 4. Mientras q al 3 ninguno. Los pares tienen dos .5 q van a ellos y los impares ninguno.
        Si tengo una distribución homogénea (la voy hacer al máximo):
        (0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4)=>1 9 valores
        (1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5) =>2 11 valores
        (2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4) =>3 9 valores
        (3.5 3.6 3.7 3.8 3.9 4.0 4.1 4.2 4.3 4.4 4.5) =>4 11 valores
        (4.6 4.7 4.8 4.9 5.0 5.1 5.2 5.3 5.4)=> 5 9 valores…
        11 valores para los pares y 9 a los impares.
        Lo dicho, si hacéis un sorteo en q entre esto en juego a mi me dais un numero par.

  3. darth_suicune

    Yo tampoco sabia esto. Entonces, si he entendido bien:
    2.5 – 1.5 = 1
    round(2.5) – round(1.5) = 0
    3.5 – 2.5 = 1
    round(3.5) – round(2.5) = 2

    IEEE, you’re drunk, go home.

    En cualquier caso, he estado buscando mas informacion porque esto me parecia muy loco, y la explicacion que das no aclara bien (que es ser justo con los numeros?) y he encontrado esto:

    http://mathematica.stackexchange.com/a/2120

    Aqui lo explican bastante mejor. En situaciones estadisticas o economicas (que serian uno de los principales lugares para el redondeo), donde el .5 aparece mucho, el redondeo hacia el valor superior provocaria una modificacion mayor en la media tras el redondeo que la que se provoca al aplicar este otro sistema (para entradas aleatorias).

    • Sí, es el motivo por el que se usaba en banca y acabó imponiéndose en los lenguajes de programación. También he visto luego que a este redondeo se le llama Gaussiano y parece ser que el propio Gauss lo definió como más correcto cuando posteriormente quieres hacer cálculos con esos números redondeados. Los errores en cálculos posteriores son menores que con el redondeo “al alza”.

      El ejemplo que has puesto deja al redondeo bastante mal, pero si haces:

      2.5+1.5 = 4
      RoundPar(2.5)+roundPar(1.5)=4
      RoundNormal(2.5)+roundNormal(1.5) = 5

      3.5 + 2.5 = 6
      RoundPar(3.5)+roundPar(2.5) = 6
      RoundNormal(3.5)+roundNormal(2.5)=7

      Podríamos decir redondeo normal you’re drunk, go home 😉

      Muchas gracias por los comentarios, he escrito la entrada en caliente y con estos comentarios está quedando estupendamente 😉

      • Que bueno.
        Imagino que depende del objetivo del redondeo. No veo mal que se acoplen intervalos abiertos con cerrados para discretizar la recta real (que es lo que se plantea con este redondeo, a favor de considerar realmente los puntos medios reales) pero tampoco veo mal seguir usando el redondeo usando intervalos semiabiertos, dependiendo para que.
        En el caso que decíais antes el .0 contabilizaría en el grupo .0 .1 .2 .3 .4, frente a .5 .6 .7 .8 .9, por lo que quedarían la misma cantidad de elementos.
        Y si usamos el roundpar(3.5)+roundpar(3.5) = 6…?
        Parece que usando intervalos cerrados (con abiertos) parece que el punto medio se mantiene identificado con valor real, sin embargo usando intervalos semiabiertos [a, b), el punto medio exacto sería un intervalo (b-e,b] con e -> 0,
        Realmente es un asunto interesante que da que pensar…
        Creo recordar que además la amplitud de los intervalos abiertos o cerrados es la misma por lo que no habría diferencia en cuanto al tamaño de los mismos … O podemos considerar que los intervalos abiertos son menores que los cerrados en un factor e -> 0…?
        Voy a tomarme el cabrito con vino y después vuelvo a pensar

      • Mira, esta explicación con las sumas redondeadas me convence más.

  4. Estoy que no salgo de mi asombro. Entre las nuevas palabras que va incluyendo la RAE y esto, siento que mis años de colegio carecen de toda validez :S
    La becaria,
    http://diariodeunabecaria.WordPress.com

  5. Ja, Ja, gracias por informar José M., yo tampoco tenía ni idea de este cambio.
    Adjunto el dibujito de Wolfram: antes todos los intervalos eran semiabiertos y ahora se van intercalando un abierto y un cerrado.
    Yo diría que con la nueva definición la gráfica de la función queda más bonita,… je, je…
    http://mathworld.wolfram.com/NearestIntegerFunction.html
    ¡Saludos!

  1. Pingback: Ya no se redondea como en los viejos tiempos

¡Un comentario para un ex-leproso!

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: