JavaScript BigInt
Aprenda JavaScript BigInt: como criar e usar inteiros de precisão arbitrária, regras aritméticas e de comparação, armadilhas de conversão e casos de uso reais.
Introdução ao JavaScript BigInt
BigInt é um tipo primitivo nativo do JavaScript que representa números inteiros de tamanho arbitrário — inteiros muito maiores do que o tipo Number comum consegue representar com precisão. Este guia explica por que o BigInt existe, como criá-lo e operá-lo, onde ele brilha (finanças, criptografia, computação em larga escala) e os cuidados que você deve ter.
Por Que o BigInt Existe
O tipo Number do JavaScript é um valor de ponto flutuante de 64 bits. Ele só consegue representar inteiros com exatidão até Number.MAX_SAFE_INTEGER, que é 2^53 - 1 (9007199254740991). Além desse valor, a aritmética comum perde precisão silenciosamente:
Quando você precisa de inteiros exatos maiores que esse valor — IDs de banco de dados, moedas na menor unidade, chaves criptográficas, fatoriais — BigInt é a solução.
Entendendo o BigInt em JavaScript
Um BigInt é um tipo primitivo distinto de Number. O operador typeof retorna "bigint", e ele possui suas próprias regras aritméticas.
Sintaxe e Criação
Crie um BigInt anexando n a um literal inteiro ou chamando a função BigInt() com um número ou uma string.
Use a forma de string quando o valor vier de uma entrada ou exceder o que um literal numérico pode expressar com segurança. Passar um número não inteiro (como BigInt(1.5)) lança um RangeError.
Operações Básicas com BigInt
BigInt suporta os mesmos operadores aritméticos que Number, mas ambos os operandos devem ser BigInt. A divisão trunca em direção ao zero — não há parte fracionária.
Note que first / second é 2n, não 2.5 — a divisão com BigInt descarta o resto em vez de produzir uma fração.
Comparando BigInt e Number
Embora sejam tipos diferentes, BigInt e Number podem ser comparados com operadores relacionais e o operador de igualdade fraca ==. Apenas a igualdade estrita === distingue os tipos, pois ela também verifica o tipo.
Veja operadores de comparação para entender como == e === diferem em geral.
Limitações e Coerção de Tipos
Apesar de poderoso, BigInt tem limitações específicas em relação ao tipo Number padrão:
- Sem Coerção Implícita em Aritmética: Não é possível somar, multiplicar etc. um
BigIntcom umNumber— isso lança umTypeError. Converta um dos lados primeiro. - Funções Math: Os métodos padrão de
Math(por exemplo,Math.sqrt(),Math.floor()) não aceitam argumentosBigInte lançarão um erro. - Sem Mais Unário:
+10nlança um erro — useNumber(10n)em vez disso. - JSON:
JSON.stringifynão consegue serializar umBigInte lança umTypeError; converta-o para string manualmente antes. - Conversão Explícita: Converta entre tipos com
Number(bigint)ouBigInt(number). A conversão paraNumberpode perder precisão em valores muito grandes.
Aplicações Práticas do BigInt
A capacidade do BigInt de lidar com números grandes com precisão o torna indispensável em cálculos financeiros, criptografia e computação em larga escala.
Cálculos Financeiros
Em aplicações financeiras, BigInt ajuda a evitar os erros de arredondamento associados aos números de ponto flutuante.
Este exemplo ilustra o uso de BigInt para aritmética de alta precisão em contextos financeiros, garantindo exatidão nas transações.
BigInt é uma ferramenta essencial em criptografia, desempenhando um papel fundamental na geração de números primos grandes. Esses números são fundamentais para os mecanismos de segurança dos algoritmos de criptografia, garantindo que os dados sejam protegidos com eficácia.
Computação de Alto Desempenho
O exemplo a seguir demonstra o uso de BigInt na multiplicação de matrizes para processamento de dados em larga escala, garantindo precisão e eficiência. Incluiremos uma implementação completa da função de multiplicação de matrizes usando BigInt. Isso envolve inicializar matrizes, preenchê-las com valores BigInt e realizar a multiplicação. Veja um exemplo real passo a passo:
Passo 1: Inicializar a Matriz
Primeiro, criamos uma função para inicializar uma matriz com as dimensões fornecidas, preenchida com zeros BigInt.
function initializeMatrix(rows, cols) {
let matrix = new Array(rows);
for (let i = 0; i < rows; i++) {
matrix[i] = new Array(cols).fill(0n);
}
return matrix;
}Passo 2: Função de Multiplicação de Matrizes
Em seguida, definimos a função para realizar a multiplicação de matrizes. Ambas as matrizes de entrada devem conter valores BigInt, e a matriz resultante também conterá valores BigInt.
function multiplyMatrices(matrixA, matrixB) {
if (matrixA[0].length !== matrixB.length) {
throw new Error('Number of columns in Matrix A must equal number of rows in Matrix B');
}
let resultMatrix = initializeMatrix(matrixA.length, matrixB[0].length);
for (let i = 0; i < matrixA.length; i++) {
for (let j = 0; j < matrixB[0].length; j++) {
let sum = 0n;
for (let k = 0; k < matrixA[0].length; k++) {
sum += matrixA[i][k] * matrixB[k][j];
}
resultMatrix[i][j] = sum;
}
}
return resultMatrix;
}Passo 3: Matrizes de Exemplo e Multiplicação
Por fim, criamos algumas matrizes de exemplo e realizamos a multiplicação. As matrizes são preenchidas com valores BigInt.
Explicação da Saída
Este exemplo multiplica duas matrizes 2x2 preenchidas com BigInts. A saída será uma nova matriz onde cada elemento é o resultado das regras de multiplicação de matrizes aplicadas a valores BigInt. Veja como a multiplicação fica:
Result[0][0]= (1n * 2n) + (2n * 1n) = 2n + 2n = 4nResult[0][1]= (1n * 0n) + (2n * 2n) = 0n + 4n = 4nResult[1][0]= (3n * 2n) + (4n * 1n) = 6n + 4n = 10nResult[1][1]= (3n * 0n) + (4n * 2n) = 0n + 8n = 8n
Essa funcionalidade demonstra como BigInt pode ser utilizado para lidar com números grandes em computações complexas como a multiplicação de matrizes, garantindo precisão e desempenho em aplicações JavaScript que exigem cálculos numéricos em larga escala.
Use BigInt com cautela, pois ele pode impactar o desempenho devido à maior demanda de memória e processamento em comparação com números padrão. Use-o apenas quando necessário para lidar com inteiros muito grandes.
Boas Práticas para Usar BigInt em JavaScript
Ao incorporar BigInt em seus projetos JavaScript, considere as seguintes boas práticas para otimizar o desempenho e a manutenibilidade:
- Consistência de Tipos de Dados: Evite misturar BigInt com outros tipos numéricos. A coerção entre BigInt e Number pode gerar erros ou comportamentos inesperados. Certifique-se de que todos os operandos em cálculos sejam do tipo BigInt quando necessário.
- Adequação ao Caso de Uso: Empregue BigInt apenas quando lidar com números fora do intervalo seguro para números JavaScript padrão. O uso excessivo de BigInt pode gerar sobrecarga de desempenho.
- Considerações de Memória: Embora BigInt possa lidar com números muito grandes, fique atento ao uso de memória nas suas aplicações, especialmente em ambientes com recursos limitados.
- Verificação de Compatibilidade: Antes de usar BigInt, verifique a compatibilidade com o ambiente JavaScript alvo, pois navegadores mais antigos ou alguns motores JavaScript podem não suportá-lo.
- Algoritmos Eficientes: Ao realizar operações com BigInt, especialmente em laços ou funções recursivas, otimize seus algoritmos para minimizar impactos no desempenho.
Entendendo Polyfills para BigInt em JavaScript
O tipo BigInt do JavaScript é essencial para lidar com inteiros muito grandes, mas não é suportado em todos os ambientes. Para garantir compatibilidade entre diferentes navegadores e motores JavaScript, especialmente os mais antigos, usar polyfill para BigInt pode ser uma abordagem prática.
O Que é Polyfilling?
Polyfilling é uma técnica usada para implementar funcionalidades em navegadores web que não as suportam nativamente. Consiste em incluir um script que adiciona a funcionalidade ausente ao ambiente JavaScript do navegador, permitindo que os desenvolvedores usem recursos modernos sem precisar esperar que todos os usuários migrem para navegadores que os suportam.
Polyfilling de BigInt
Como BigInt é uma adição relativamente recente ao JavaScript, nem todos os ambientes o suportam. O polyfilling permite usar BigInt nesses ambientes não suportados simulando sua funcionalidade. Isso pode ser crucial para aplicações que exigem cálculos de alta precisão em ambientes onde atualizar para a versão mais recente do navegador não é viável.
Implementando um Polyfill para BigInt
Implementar um polyfill para BigInt envolve criar ou incluir uma biblioteca que imite o comportamento do BigInt. Veja uma demonstração conceitual simples de como um wrapper de polyfill poderia ser estruturado:
// Conceptual demonstration only. A true BigInt polyfill is complex and impractical.
// This example uses Number conversion internally for simplicity and is not suitable
// for production large-integer handling.
if (typeof BigInt === "undefined") {
window.BigInt = function(value) {
return {
value: value,
toString: function() { return value + "n"; },
add: function(other) { return BigInt(Number(this.value) + Number(other.value)); },
subtract: function(other) { return BigInt(Number(this.value) - Number(other.value)); }
};
};
}Limitações do Polyfilling de BigInt
Embora os polyfills possam fornecer compatibilidade retroativa, eles não são um substituto perfeito para implementações nativas:
- Desempenho: Polyfills não conseguem igualar o desempenho das operações nativas de BigInt, pois são implementados em JavaScript em vez de código de baixo nível otimizado pelos fornecedores de navegadores.
- Complexidade: Imitar com precisão todos os aspectos de um recurso complexo como BigInt pode ser desafiador e pode levar a bugs ou inconsistências.
- Manutenção: Manter o polyfill atualizado com quaisquer alterações na especificação oficial do BigInt requer manutenção contínua.
Considere usar um polyfill para BigInt a fim de habilitar compatibilidade em navegadores mais antigos que não suportam BigInt nativamente. No entanto, esteja ciente de que os polyfills podem não oferecer o mesmo desempenho que as implementações nativas e devem ser usados como uma solução temporária até que o suporte nativo esteja mais amplamente disponível.
Conclusão
BigInt permite que o JavaScript represente inteiros de qualquer tamanho com precisão exata, preenchendo a lacuna deixada pelo limite seguro de 53 bits do tipo Number. Recorra a ele sempre que um inteiro puder exceder Number.MAX_SAFE_INTEGER — grandes IDs de banco de dados, moedas em unidades menores, valores criptográficos e matemática com números grandes — mas mantenha o Number para cálculos cotidianos onde frações e métodos Math são importantes. Lembre-se da regra principal: nunca misture BigInt e Number em operações aritméticas sem uma conversão explícita.
Tópicos relacionados
- JavaScript Numbers — o tipo numérico padrão e seu limite de inteiros seguros.
- JavaScript Math — auxiliares matemáticos (que funcionam com
Number, não comBigInt). - JavaScript Data Types — onde
bigintse encaixa entre os primitivos. - Comparison Operators — comportamento de
==vs===usado acima.