Curiosidades numéricas em JavaScript: por que 0.1 + 0.2 não é 0.3 e outras surpresas

0.1 + 0.2 === 0.3? A resposta é não

Quem nunca se deparou com esse trecho e ficou de queixo caído?

console.log(0.1 + 0.2);          // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3);  // false

O motivo está na forma como o padrão IEEE 754 representa números fracionários em binário. Valores como 0.1 e 0.2 viram dízimas periódicas binárias; ao serem truncados para 64 bits, ficam ligeiramente diferentes. A soma dessas aproximações gera o famigerado 0.30000000000000004.

Como conviver com isso

  • Compare com tolerância: ``` const iguais = (a, b) => Math.abs(a - b) < 1e-10;
  • Trabalhe com inteiros quando possível: ``` const somaCentavos = (a, b) => (a * 100 + b * 100) / 100; somaCentavos(0.1, 0.2); // 0.3
  • Bibliotecas como decimal.js ou big.js fornecem aritmética de ponto fixo.

Number.MIN_VALUE é positivo e minúsculo

Muitos acham que Number.MIN_VALUE seria o "menor número possível". Na verdade ele é o menor número positivo normalizado representável: 5e-324.

console.log(Number.MIN_VALUE);        // 5e-324
console.log(Number.MIN_VALUE > 0);   // true

Para o maior valor negativo use -Number.MAX_VALUE.

parseInt("Infinity", ?) — uma máquina de surpresas

O comportamento de parseInt com a string "Infinity" varia conforme a base:

parseInt("Infinity", 10); // NaN
parseInt("Infinity", 19); // 18   (só "I" é válido, I = 18)
parseInt("Infinity", 24); // 151176378
parseInt("Infinity", 36); // 1461559270678

A explicação: cada letra possui um valor numérico (I=18, N=23, F=15…). A função lê da esquerda até o primeiro caractere inválido para aquela base. Portanto, em base 24, "Inf" vira 18×24² + 23×24 + 15 = 10 935, mas o valor real pode variar conforme a quentidade de caracteres aceitos.

Evite surpresas validando a entradda:

function paraInteiro(str, base = 10) {
  if (/^-?Infinity$/i.test(str)) return NaN;
  return parseInt(str, base);
}

Math.max() < Math.min() — verdade absurda

Sem argumentos, os métodos retornam os extremos do conjunto dos reais:

Math.max(); // -Infinity
Math.min(); //  Infinity
console.log(Math.max() < Math.min()); // true

Isso garante identidade matemática: o máximo de um conjunto vazio deve ser menor que qualquer número, e o mínimo deve ser maior. Proteja-se em arrays vazios:

const maiorOuNada = arr =>
  arr.length ? Math.max(...arr) : undefined;

Resumo rápido

  • Imprecisão de ponto flutuante é esperada; use tolerância ou bibliotecas.
  • Number.MIN_VALUE é o menor positivo, não o menor absoluto.
  • parseInt com bases não-decimais pode interpretar letras; sempre valide.
  • Math.max() e Math.min() sem argumentos retornam -Infinity e Infinity respectivamente.

Tags: IEEE-754 parseInt Number.MIN_VALUE Math.max Math.min

Publicado em 8-23 18:24