Necesito realizar ciertas operaciones con operadores bit a bit, digamos que tenemos este entero sin signo de 40 bits:
1071698660929 cuando le aplico un operador OR y un operador de desplazamiento a la derecha sin signo, obtuve este entero negativo
Entrada : (1071698660929 >>> 0) | 0b0
Salida : -2043163071
Me di cuenta de que siempre que el número tenga 31 bits, no tengo ningún problema para agregar un 0B0 pero cuando el número es mayor que 31 bits, se vuelve negativo aunque esté usando el operador de desplazamiento a la derecha sin signo:
Retorno binario de 32 bits -1 : (0b11111111111111111111111111111111 >>> 0) | 0
Retorno binario de 31 bits 2147483647 : (0b1111111111111111111111111111111 >>> 0) | 0
Así que tengo un par de preguntas:
Number.MAX_SAFE_INTEGER.toString(2).length , por lo que estoy dentro de los límites seguros de enteros.(1071698660929 >>> 0) | 0b0 devuelve 1071698660929 en lugar de -2043163071 ?Los operadores bit a bit implícitamente convierten sus operandos en enteros de 32 bits (con o sin signo, según el operador). En el proceso, los números con más de 32 bits obtienen sus bits más significativos descartados :
Before: 11100110111110100000000000000110000000000001 After: 10100000000000000110000000000001 La única excepción a esta regla es (relativamente) un niño nuevo en el bloque primitivo, tipo BigInt : todas las operaciones bit a bit ( & , | , ^ ) y casi todos los turnos están sobrecargados para ese tipo.
Esto abre una salida a su problema: simplemente use BigInt en lugar de un number simple, ya sea explícitamente, así:
const bigIntee = BigInt(1071698660929); // note no `new` here! ... o, si realmente tiene que usar literal, agregándole n :
const bigIntee = 1071698660929n; // also works Tenga en cuenta que si un operando es BigInt , otro también debería ser BigInt . Así que esto...
bigIntee | 0... hará que JS se enoje con tus patéticos intentos de volver a los felices tiempos de anarquía tipográfica de los 90. Para ser más específico, obtendrá un TypeError directamente hacia usted:
Cannot mix BigInt and other types, use explicit conversionsSin embargo, esto es fácilmente reparable: solo aplique cualquiera de los trucos de conversión mencionados anteriormente al segundo operando también.
bigIntee | 0n // or bigIntee | BigInt(0) Ambos trabajos. Ignorar 0 siendo, bueno, no realmente un tipo Biggus Integerus ; aquí reina la seguridad del tipo.
Aún así, hay un problema: >>> (operador de desplazamiento a la derecha sin firmar) no se puede usar en BigInts. Si intenta hacerlo, obtendrá un error bastante específico:
bigIntee >>> 0n // Uncaught TypeError: BigInts have no unsigned right shift, use >> instead... lo cual tiene mucho sentido (y deseamos que todos los errores arrojados por JS fueran tan específicos).