Números e o objeto Math
Esta aula aborda o sistema de números em JavaScript, incluindo ponto flutuante e suas armadilhas, o objeto Number e seus métodos, o objeto Math para operações matemáticas e uma introdução ao BigInt para inteiros grandes. O aluno aprenderá a trabalhar com números de forma segura e eficiente.
Números são fundamentais em qualquer linguagem de programação, e JavaScript oferece um sistema numérico flexível, porém com peculiaridades. Diferente de muitas linguagens que separam inteiros de ponto flutuante, JavaScript usa um único tipo Number baseado no padrão IEEE 754 de 64 bits para todos os números de ponto flutuante. Isso traz vantagens de simplicidade, mas também armadilhas que podem causar erros sutis. Além disso, o JavaScript moderno introduziu o BigInt para representar inteiros arbitrariamente grandes. Nesta aula, vamos explorar esses tópicos com profundidade, incluindo métodos úteis do objeto Number e funções matemáticas do objeto Math.
Vamos começar entendendo como o JavaScript lida com números, especialmente as imprecisões do ponto flutuante, e como evitá-las. Em seguida, veremos métodos estáticos e de instância do objeto Number, como isNaN(), isFinite(), toFixed() e toPrecision(). O objeto Math fornece funções como Math.round(), Math.random() e constantes como Math.PI. Por fim, apresentaremos o BigInt, sua sintaxe e usos.
Ponto flutuante e armadilhas
Em JavaScript, todos os números são armazenados como ponto flutuante de 64 bits (double precision). Isso significa que há um número finito de valores representáveis, o que leva a imprecisões em operações que parecem simples. Por exemplo, 0.1 + 0.2 não resulta exatamente em 0.3 devido à representação binária.
O problema ocorre porque frações decimais como 0.1 não podem ser representadas exatamente em binário, assim como 1/3 não pode ser representado exatamente em decimal. O JavaScript arredonda para o valor mais próximo possível, levando a pequenos erros. Isso pode causar problemas em comparações e cálculos financeiros. Uma técnica comum para contornar isso é usar arredondamento com toFixed() ou trabalhar com inteiros (centavos em vez de reais).
Exemplo de código:
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// Solução: arredondar para evitar comparação direta
const soma = (0.1 * 10 + 0.2 * 10) / 10; // 0.3
console.log(soma === 0.3); // true
// Ou usar toFixed
const valor = 0.1 + 0.2;
console.log(Number(valor.toFixed(2))); // 0.3
Number e métodos
O objeto Number é um wrapper para valores numéricos. Ele fornece propriedades e métodos úteis. As propriedades incluem Number.MAX_VALUE, Number.MIN_VALUE, Number.POSITIVE_INFINITY, Number.NaN etc. Métodos estáticos como Number.isNaN() e Number.isFinite() são mais robustos que a função global isNaN().
Métodos de instância incluem toFixed(), toPrecision(), toString() e toExponential(). toFixed() retorna uma string com um número fixo de casas decimais; toPrecision() retorna uma string com um número específico de dígitos significativos. Cuidado: esses métodos retornam strings, não números.
Exemplo de código:
const num = 123.456789;
console.log(Number.isNaN(num)); // false
console.log(Number.isFinite(num)); // true
console.log(num.toFixed(2)); // "123.46"
console.log(num.toPrecision(4)); // "123.5"
console.log(num.toString(16)); // "7b.74e9b..." (hexadecimal)
// Convertendo string para número
console.log(Number("123")); // 123
console.log(Number("12.3")); // 12.3
console.log(Number("abc")); // NaN
Objeto Math
O objeto Math é um objeto global que contém funções e constantes matemáticas. Não é um construtor, então não usamos new Math(). Ele fornece funções como Math.round(), Math.floor(), Math.ceil(), Math.random(), Math.pow(), Math.sqrt(), Math.abs(), entre outras. Constantes como Math.PI e Math.E também estão disponíveis.
Para arredondamento: Math.round() arredonda para o inteiro mais próximo; Math.floor() arredonda para baixo; Math.ceil() arredonda para cima. Math.random() gera um número pseudoaleatório entre 0 (inclusivo) e 1 (exclusivo). Para gerar um número em um intervalo, multiplique pelo tamanho e adicione o mínimo.
Exemplo de código:
console.log(Math.PI); // 3.141592653589793
console.log(Math.round(4.7)); // 5
console.log(Math.floor(4.7)); // 4
console.log(Math.ceil(4.3)); // 5
console.log(Math.pow(2, 3)); // 8
console.log(Math.sqrt(16)); // 4
console.log(Math.abs(-5)); // 5
// Número aleatório entre 1 e 10
const aleatorio = Math.floor(Math.random() * 10) + 1;
console.log(aleatorio);
BigInt (introdução)
O BigInt é um tipo de dado introduzido no ECMAScript 2020 para representar inteiros de tamanho arbitrário. Ele é criado adicionando n ao final de um número inteiro ou usando o construtor BigInt(). Diferente de Number, BigInt pode representar números inteiros muito grandes sem perda de precisão.
Operações aritméticas entre BigInt e Number não são permitidas diretamente (erro de tipo). É necessário converter explicitamente. BigInt não suporta operações de ponto flutuante (divisão resulta em inteiro truncado). Métodos como Math não funcionam com BigInt.
Exemplo de código:
const big1 = 123456789012345678901234567890n;
const big2 = BigInt("987654321098765432109876543210");
console.log(big1 + big2); // 1111111110111111111011111111100n
console.log(big1 * 2n); // 246913578024691357802469135780n
// Erro: misturar tipos
// console.log(big1 + 1); // TypeError: Cannot mix BigInt and other types
// Conversão
const num = Number(big1); // pode perder precisão
console.log(num); // 1.2345678901234568e+29
Boas práticas e observações finais
Ao trabalhar com números em JavaScript, prefira Number.isNaN() e Number.isFinite() para verificações mais seguras. Evite comparações diretas de números de ponto flutuante; use uma margem de erro (epsilon) ou converta para inteiros quando possível. Para cálculos financeiros, considere usar bibliotecas como decimal.js ou trabalhar com centavos em inteiros. BigInt é ideal para números inteiros muito grandes, mas lembre-se de que não há suporte para decimais. O objeto Math é estático e não precisa de instância.
Referências
- MDN: Number
- MDN: Math
- MDN: BigInt
- MDN: Operadores Aritméticos
- Floating Point Guide
- ECMAScript Specification
Exercícios
Explique por que
0.1 + 0.2 !== 0.3em JavaScript e sugira uma maneira de fazer a comparação corretamente.✓ Resposta: Isso ocorre porque 0.1 e 0.2 não podem ser representados exatamente em binário, causando pequenos erros de arredondamento. Para comparar, pode-se usar uma margem de tolerância (epsilon) ou arredondar para um número fixo de casas decimais antes da comparação. Exemplo:Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILONouNumber((0.1 + 0.2).toFixed(2)) === 0.3.Escreva uma função que receba um número e retorne uma string formatada com duas casas decimais, usando
toFixed().✓ Resposta:function formatDecimal(num) { return num.toFixed(2); } console.log(formatDecimal(123.456)); // "123.46"Use
Math.random()para gerar um número inteiro aleatório entre 1 e 100 (inclusive).✓ Resposta:const aleatorio = Math.floor(Math.random() * 100) + 1; console.log(aleatorio);Declare um
BigIntcom o valor12345678901234567890e some com outroBigIntde sua escolha. Exiba o resultado.✓ Resposta:const bigA = 12345678901234567890n; const bigB = 9876543210987654321n; console.log(bigA + bigB); // 22222222112222222211nCalcule a raiz quadrada de 144 usando
Math.sqrt()e o valor deMath.PIarredondado para 4 casas decimais.✓ Resposta:console.log(Math.sqrt(144)); // 12 console.log(Math.PI.toFixed(4)); // "3.1416"