Javascript Logo
en español

Errores de coma flotante en JavaScript

Fácil
-
2 min. lectura

Cuando haces con javascript

0.1 + 0.2 === 0.3

y el resultado es false, no es un bug. Es la naturaleza misma de cómo los ordenadores representan los números.  

Qué es coma flotante

JavaScript (como la mayoría de lenguajes) usa el formato IEEE-754 de 64 bits para representar números.

Este formato almacena el signo, el exponente y la parte de la fracción en binario.

El problema es que muchos números decimales no tienen representación exacta en binario.

Por ejemplo, 0.1 se convierte internamente en algo como:

0.00011001100110011001100110011001100110011001100110011...

Un número infinito que debe truncarse. Por ejllo 0.1 + 0.2 da 0.30000000000000004

Algunos ejemplos:

0.1 + 0.2        // 0.30000000000000004
0.3 - 0.2        // 0.09999999999999998
0.1 * 3          // 0.30000000000000004
0.3 / 0.1        // 2.9999999999999996

Comparar correctamente con EPSILON

En lugar de buscar igualdad exacta, usa una tolerancia con el número EPSILON

const casiIguales = (a, b) => Math.abs(a - b) < Number.EPSILON;
casiIguales(0.1 + 0.2, 0.3); // true

Number.EPSILON representa la mínima diferencia reconocible entre dos números distintos en coma flotante.

Redondeando resultados

También podemos usar toFixed si lo que queremos es representar el valor final

+(0.1 + 0.2).toFixed(2); // 0.3

O incluso podemos usar una funcón auxiliar

function redondear(valor, decimales = 2) {
  const factor = 10 ** decimales;
  return Math.round(valor * factor) / factor;
}

Aun así, lo aconsejable es que evites redondear dentro de cada paso de un cálculo largo.
Cada redondeo introduce un pequeño error que se acumula. Lo ideal es redondear solo al final, justo antes de mostrar o guardar el resultado.

Trabajando con enteros

Quizás la práctica más común cuando trabajamos con precios o contabilidad es multiplicar por 100 y trabajar con enteros para evitarnos errores. 

let a = 10;  // representa 0.10 €
let b = 20;  // representa 0.20 €
(a + b) / 100; // 0.3

Así evitas errores acumulados y mantienes control total sobre los decimales.

Uso de librerías

Cuando la precisión es crítica (finanzas, cálculos científicos...), puedes usar librerías de precisión arbitraria que está ideadas para evitarnos errores de coma flotante.

Una de las más utilizadas es decimal.js

npm install decimal.js
import { Decimal } from 'decimal.js';
new Decimal(0.1).plus(0.2).equals(0.3); // true

Otras opciones son big.js, bignumbers.js o dinero.js

Donde podemos encontrarnos errores

  • Cálculos de IVA o impuestos
  • Sumas de totales o descuentos
  • Comparaciones de precios exactos
  • Medias o porcentajes acumulativos

En todos estos casos, una pequeña desviación puede tener impacto real.
Un céntimo fuera de lugar es suficiente para romper una conciliación.