Por qué es complicado
El objeto Math de JavaScript proporciona un método para redondear a números enteros. Si queremos redondear a un número determinado de decimales, tenemos que hacerlo nosotros mismos. Este post no entra en los detalles de la aritmética de punto flotante, pero el resumen es que la mayoría de los lenguajes de programación utilizan una representación binaria de punto flotante que sólo puede aproximarse a muchas fracciones decimales. Esto da lugar a errores de redondeo para los enfoques más comunes para el redondeo en JavaScript.
Errores de redondeo
Las soluciones más comunes para el redondeo a un decimal es utilizar Number.prototype.toFixed()
, o multiplicar el flotador por alguna potencia de 10 con el fin de aprovechar Math.round()
. Ambas cosas funcionan, excepto que a veces un decimal de 5 se redondea hacia abajo en lugar de hacia arriba.
Number((1.005).toFixed(2)); // 1 instead of 1.01
Math.round(1.005*100)/100; // 1 instead of 1.01
Una solución mejor
El problema del redondeo se puede evitar utilizando números representados en notación exponencial:
Number(Math.round(1.005+'e2')+'e-2'); // 1.01
Y para abstraer eso en algo más utilizable:
function round(value, decimals) { return Number(Math.round(value+'e'+decimals)+'e-'+decimals);}round(1.005, 2); // 1.01