Quiero definir un número BigInt en JavaScript. Pero cuando lo asigno, se almacena el número incorrecto. De hecho, se suma 1 al número al almacenar.
let num = BigInt(0b0000111111111111111111111111111111111111111111111111111111111111) console.log(num) // Output: 1152921504606846976n console.log(num.toString(2)) // Output: 1000000000000000000000000000000000000000000000000000000000000 Entonces, el número almacenado es 1152921504606846976 , pero debería ser 11529215046068469765 . ¿Porqué es eso?
Convertir un número en BigInt no puede crear bits que no estaban allí antes.
0b1 (al igual que 1 ) es un número literal, por lo que crea un número.
0b1n (al igual que 1n ) es un literal BigInt, por lo que crea un BigInt.
Al escribir BigInt(0b1) , primero está creando un Número y luego convirtiéndolo en BigInt. Siempre que el valor sea 1, funciona bien; una vez que el valor exceda lo que puede almacenar sin pérdidas en un Number [1], verá que el valor del BigInt final no coincidirá con el literal que anotó. Ya sea que use literales binarios ( 0b... ), decimales o hexadecimales ( 0x... ) no cambia nada de eso.
(Y para que quede más claro: no hay razón para escribir BigInt(123n) , al igual que no escribirías Number(123) . 123n ya es un BigInt, por lo que no hay nada que convertir).
Una forma simple que no es BigInt de ilustrar lo que está sucediendo es ingresar 12345678901234567890 en la consola DevTools de su navegador favorito: puede especificar literales numéricos de cualquier longitud que desee, pero se analizarán en un "doble" IEEE754 de 64 bits, que tiene precisión limitada. Cualquier dígito adicional en el literal simplemente no se puede almacenar, aunque, por supuesto, la presencia de cada dígito afecta la magnitud del número.
[1] Nota al margen: esta condición es más sutil que simplemente decir que Number.MAX_SAFE_INTEGER es el umbral, aunque esa constante está relacionada con la situación: cualquier número entero por debajo MAX_SAFE_INTEGER se puede almacenar sin pérdidas, pero hay muchos números por encima de MAX_SAFE_INTEGER que también se puede representar exactamente. Ejemplo aleatorio: 1e20 .