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 .

Source link