No passado, os desenvolvedores lutavam com programas que faziam uso de números extremamente grandes porque o primitivo Number
JavaScript tinha um limite nos valores mínimo e máximo que podia representar corretamente.
Consequentemente, isso levou a muitas soluções alternativas instáveis, como converter grandes valores em strings ou terceirizar o trabalho para fornecedores terceirizados, o que levou a bugs e/ou grandes tamanhos de compilação.
Mas com a introdução da primitiva BigInt
na especificação ECMAScript, os desenvolvedores não precisam mais depender de soluções alternativas frágeis ou bibliotecas de terceiros. Em vez disso, BigInt
permite que eles trabalhem com segurança com números além dos limites do primitivo Number
.
Neste artigo, aprenderemos o que levou à adição da primitiva BigInt
na especificação ECMAScript, como BigInt
resolve o problema e, por último, nós’aprenderemos como começar com o BigInt
.
Por que usar BigInt
?
Porque existem muitas limitações ao usar Number
e tipos de dados em JavaScript.
Em JS, o tipo de dados Number
representa todos os números em JavaScript como número de ponto flutuante de precisão dupla usando o formato definido pelo IEEE 754, o que significa que os números em JavaScript são representados como flutuantes de precisão dupla , ou duplica para breve.
Convencionalmente, porque o primitivo Number
representa todos os números como duplos, eles sempre recebem 64 bits de memória. Com ele, números variando de-1,7 10 ^ 308 a 1,7 10 ^ 308 podem ser representados e armazenados em variáveis.
Infelizmente, não podemos trabalhar de forma confiável com todos os números dentro desse intervalo, pois a maioria deles são inteiros inseguros -representações numéricas que fazem referência a mais de um número do mundo real.
Isso ocorre porque, embora um número específico do mundo real não possa ser representado exatamente de acordo com o formato IEEE 754, ele será arredondado usando um dos “modos de arredondamento” padrão para forçar o número a aderir ao formato.
O resultado? O computador arredondará certos números de uma forma que os torne iguais a outros números que não precisam ser arredondados para garantir que seguem o formato.
Essencialmente, esses inteiros inseguros não têm sua própria representação privada; em vez disso, eles compartilham erroneamente a representação de outros números do mundo real que não precisam passar por arredondamento para se adequar ao formato.
Aqui está um exemplo:
//JS define o interger seguro máximo como um número constante.MAX_SAFE_INTEGR const safeInt=Number.MAX_SAFE_INTEGER//-> 9_007_199_254_740_991 //Se adicionarmos um, obtemos safeInt + 1//-> 9_007_199_254_740_992 ✅ //Se adicionarmos 2... safeInt + 2//-> 9_007_199_254_740_992 & # x1f926; & # x1f3fe; ♂ //Portanto, 9_007_199_254_740_992 ou (2 ^ 53) é considerado inseguro porque dois números do mundo real 9_007_199_254_740_992 e 9_007_199_254_740_993 são representados por ele. Por isso safeInt + 1===safeInt + 2//-> true
Então, o que isso significa? Usar números maiores ou menores que Number.MAX_SAFE_INTEGR
ou Number.MIN_SAFE_INTEGER
certamente causará bugs.
Muitos de nós podem não precisar se preocupar com isso, pois a faixa de quantidades numéricas que usamos está dentro dos limites de Number.MAX_SAFE_INTEGR
e Number.MIN_SAFE_INTEGR
.
No entanto, alguns desenvolvedores precisam trabalhar além desses limites, como aqueles que trabalham com finanças ou fazem cálculos constantemente com números incrivelmente grandes.
Felizmente, existe uma solução: BigInt
.
O que é BigInt
?
BigInt
é um tipo primitivo/inteiro numérico relativamente novo em JavaScript. Ele foi criado para resolver as limitações que as pessoas encontravam com as restrições de inteiros primitivos e seguros Number
.
BigInt
representa números com precisão arbitrária, o que significa que usa tanto espaço quanto necessário para armazenar e representar grandes números, em vez de tentar forçadamente representá-los usando uma quantidade fixa de memória como o Number
o tipo inteiro sim.
Você pode pensar em BigInt
e Number
como arrays estáticos e dinâmicos. BigInt
usará mais espaço se for necessário ao representar um grande número, como uma matriz dinâmica. Mas Number
só fará uso da memória fixa inicialmente atribuída a ele para representar números, como uma matriz estática.
BigInt
nos dá a capacidade de trabalhar com grandes números sem ter que nos preocupar com a possível perda de precisão (dígitos) ou problemas de representação estranhos que dificultam a precisão e criam bugs.
Primeiros passos com BigInt
Para criar um BigInt
, basta adicionar n
no final de qualquer literal inteiro. Observe que fazer isso com decimais/flutuantes lançará um RangeError
:
//Isso está certo const bigInteger=1000000000000000000000000n //Isso vai lançar um RangeError const bigInteger=1.5n//-> RangeError //Você também pode criar um BigInt com números negativos const negativeBigIntInteger=-1111111n//->-1111111n
Como alternativa, você também pode usar a função global BigInt
passando um literal inteiro como argumento.
//Isso também está certo const bigIntefer=BigInt (1000000000000000000000000000000000) //Isso ainda vai lançar um RangeError const bigInteger=BigInt (1.5)
Os literais
BigInt
também podem ser instanciados usando strings, notação binária, hexadecimal ou octal.
//Strings BigInt ("111111111111111111111111111111111111111") //-> 1111111111111111111111111111111111111n //Binário BigInt (0b100000000000000000000000000000000000000000000000000000000000000000000001111111) //-> 151115727451828646838272n //Hexadecimal BigInt (0xffffffffffffffff) //-> 95780971304118053647396689196894323976171195136475136n //Octal BigInt (0o400000000000000000000000000000000000000000000011112444) //-> 713623846352979940529142984724747568191373312n
Você não pode comparar um BigInt
e um Number
regular usando igualdade estrita (===
) porque BigInt
é um primitivo por si só.
Portanto, chamar typeof
em um literal BigInt
retornará "bigint"
em vez de "número"
, fazendo com que comparações estritas entre eles retornem falso.
const a=111111n const b=111111 a===b//-> falso
No entanto, se você usar igualdade abstrata (==
), compare um literal BigInt
com um valor de 11n
e um O literal Number
com um valor de 11
retornará true
porque os dois literais têm o mesmo valor.
const a=11n const b=11 a==b//-> verdadeiro
Todas as operações aritméticas ( +
, -
, /
, *
) podem ser realizadas em Literais BigInt
, com exceção de mais unário. Por exemplo, você não pode escrever + 11n
como faria +11
.
Por outro lado, você pode incrementar literais BigInt
com ++
e diminuí-los com -
.
Além disso, a aritmética com literais BigInt
deve estar entre literais BigInt
. Um literal Number
não pode ser um operando em uma operação aritmética envolvendo um BigInt
. Tentar fazer isso resultará em um TypeError
.
//Podemos fazer isso 11n + 12n//-> 23n //Mas não podemos fazer isso 11n + 12//-> TypeError
Além disso, como a aritmética BigInt
retorna um BigInt
, o valor de retorno será sempre um número inteiro do tipo "bigint"
.
5n/3n//-> 1n 19n/2n//-> 9n
Os literais
BigInt
maiores que 0n
são todos forçados a true
. Enquanto 0n
, é forçado a false
.
if (5n) { //Bloco de código será executado } if (0n) { //Bloco de código não será executado }
Além disso, BigInt (true)
retornará 1n
.
BigInt (true)===1n//-> true
A função global BigInt
contém dois métodos estáticos que restringirão uma representação BigInt
para usar um número de bits que é especificado como o primeiro parâmetro de ambos os métodos.
Assim que BigInt
estiver dentro do limite de espaço especificado, ele será retornado como um inteiro assinado ou não, dependendo do método usado.
O primeiro método, BigInt.asIntN (bits,
, retorna o
como um inteiro assinado.
O segundo método, BigInt.asUintN (bits,
retorna o
como um inteiro sem sinal.
Esses métodos podem ser úteis para gerenciamento explícito de memória. Sabemos que, por padrão, BigInt
usa quantos bits forem necessários para representar um número, mas, se você estiver sem memória e souber a faixa dos valores numéricos para sua aplicação, esses métodos irão ser útil.
//Para representar números BigInt como inteiros com sinal BigInt.asIntN (bits,) //Para representar números BigInt como inteiros sem sinal BigInt.asUintN (bits, )
Conclusão
Depois de ler este artigo, você terá uma compreensão mais profunda do que é o BigInt
, os problemas que ele resolve e como usá-lo.
Obrigado por ler!
A postagem Por que (e como) usar o BigInt
apareceu primeiro no LogRocket Blog .