En ocasiones puede que necesitemos redondear un número entero a su valor en decenas (también se podría aplicar a centenas, miles, etc). Por ejemplo, en mi caso, fue necesario para generar un calendario y pasar del año actual a su década correspondiente.

En este artículo veremos cuatro funciones JavaScript para realizar dicha operación y cuál nos ofrece mejores resultados.

Función 1. Multiplicación y división

Esta primera función se divide el número entre 10, posteriormente se convierte a entero (por lo que se pierde la unidad que habría quedado en la parte decimal) y finalmente se multiplica por 10 para obtener el valor redondeado.

function round(value) {
    return parseInt(value / 10) * 10;
}

Función 2. Resto

En este caso, se calculará el resto sobre 10 del valor indicado restándose al valor original. De esta forma, puesto que obtenemos el valor de unidad lo podremos restar al número original.

function round(value) {
    return value - (value % 10);
}

Función 3. Redondeo con Math

La última función es parecida a la primera, pero en lugar de pasar a entero el valor, realiza un redondeo usando la librería Math para posteriormente multiplicar por 10. Curiosamente, pese a utilizar la librería Math y tener una condición en su interior, pudiera parecer que es más lenta que la primera opción, pero os sorprenderá el resultado.

function round(value) {
    if (0 > value) {
        return Math.ceil(value / 10) * 10;
    }
    return Math.floor(value / 10) * 10;
}

Función 4. Uso de cadenas

Algunas personas están cómodas con el uso de cadenas, pero supone una gran penalización de rendimiento. En esta función, se convierte a cadena el valor, se suprime el último carácter y finalmente se concatena el 0, realizando un parseo a entero. El resultado es nefasto como podréis observar en la tabla de tiempos.

function round(value) {
    return parseInt(('' + value).slice(0, -1) + '0');
}

La batería de pruebas

El código para todas las pruebas será el mismo, por un lado tendremos un HTML muy básico que mostrará una tabla de resultados:

<table>
    <tr id="data">
        <th>Results</th>
    </tr>
</table>

Por otro lado, el código de pruebas también es muy sencillo. Consiste en una función que realiza un bucle de 10 pasos, en el que en cada paso se llama un millón de veces a la función encargada de redondear con valores comprendidos entre -500.000 y 500.000. Por otro lado, se dispone de una función con la que se añade cada resultado a la tabla HTML (Se podría haber mostrado por consola simplemente, pero así queda más visual).

function addResult(value, row, last) {
    var node = document.createElement(last ? 'th' : 'td'),
        textnode = document.createTextNode(value);

    node.appendChild(textnode);
    row.appendChild(node);
}

function test() {
    var roundTime = 0,
        row = document.getElementById('data'),
        lap, startTime, i, endTime, currentResult;

    for (lap = 0; lap < 10; ++lap) {
        startTime = new Date();
        for (i = 0; i < 10000000; ++i) {
            round(-5000000 + i);
        }
        endTime = new Date();

        currentResult = endTime.getTime() - startTime.getTime()
        roundTime += currentResult;
        addResult(currentResult, row, false);
    }

    addResult((roundTime / 10) + 'ms', row, true);
}

test();

Resultados

Tras ejecutar el código anterior con cada función de redondeo, los resultados han sido los siguientes (los valores son en milisegundos):

Función Paso 1 Paso 2 Paso 3 Paso 4 Paso 5 Paso 6 Paso 7 Paso 8 Paso 9 Paso 10 Media
1 184 183 175 172 171 175 174 180 171 178 176.3
2 10 10 7 7 7 7 6 7 7 7 7.5
3 102 99 94 92 94 94 95 93 95 93 95.1
4 3284 3584 4267 3562 3790 4114 3947 3558 3461 3765 3733.2

En conclusión, como se puede observar, a la hora de redondear tenemos una clara vencedora. El uso de la función 2, con cálculo de resto, es más de 20 veces más rápida que la función 1 y 10 veces más rápida que la función 3. No hace falta decir, que el uso de cadenas para realizar esta operación no es nada aconsejable, teniendo una media de 3.7 segundos por paso.

Seguro que conocéis algún otro método para realizar esta operación, así que no dudéis en compartirla en los comentarios.

Enlaces
Método 1 en JSFiddle
Método 2 en JSFiddle
Método 3 en JSFiddle
Método 4 en JSFiddle

Comparte este artículo con quien quieras
Internacionalización en ES6 1: La clase Collator
Internacionalización en ES6 2: La clase DateTimeFormat

Leave a Comment

Your email address will not be published. Required fields are marked *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.