javascript - etf - bitwise traduccion
Y bit a bit en Javascript con un entero de 64 bits (4)
Estoy buscando una forma de realizar un bit a bit en un entero de 64 bits en JavaScript.
JavaScript convertirá todos sus valores dobles en enteros de 32 bits con signo para realizar las operaciones a nivel de bits ( detalles aquí ).
Aquí está el código para los números AND int64, puede reemplazar AND con otra operación bitwise
function and(v1, v2) {
var hi = 0x80000000;
var low = 0x7fffffff;
var hi1 = ~~(v1 / hi);
var hi2 = ~~(v2 / hi);
var low1 = v1 & low;
var low2 = v2 & low;
var h = hi1 & hi2;
var l = low1 & low2;
return h*hi + l;
}
Javascript no admite enteros de 64 bits de la caja. Esto es lo que terminé haciendo:
- Encontrado long.js , una implementación larga independiente en github.
- Convierta el valor de cadena que representa el número de 64 bits a
Long
. - Extraer los valores altos y bajos de 32 bits.
- Haga un bit a bit de 32 bits y entre los bits alto y bajo, por separado.
- Inicialice un nuevo bit de 64 bit desde el bit alto y bajo.
- Si el número es> 0, entonces hay una correlación entre los dos números
Nota : para que el ejemplo de código a continuación funcione, necesita cargar long.js
// Handy to output leading zeros to make it easier to compare the bits when outputting to the console
function zeroPad(num, places){
var zero = places - num.length + 1;
return Array(+(zero > 0 && zero)).join(''0'') + num;
}
// 2^3 = 8
var val1 = Long.fromString(''8'', 10);
var val1High = val1.getHighBitsUnsigned();
var val1Low = val1.getLowBitsUnsigned();
// 2^61 = 2305843009213693960
var val2 = Long.fromString(''2305843009213693960'', 10);
var val2High = val2.getHighBitsUnsigned();
var val2Low = val2.getLowBitsUnsigned();
console.log(''2^3 & (2^3 + 2^63)'')
console.log(zeroPad(val1.toString(2), 64));
console.log(zeroPad(val2.toString(2), 64));
var bitwiseAndResult = Long.fromBits(val1Low & val2Low, val1High & val2High, true);
console.log(bitwiseAndResult);
console.log(zeroPad(bitwiseAndResult.toString(2), 64));
console.log(''Correlation betwen val1 and val2 ?'');
console.log(bitwiseAndResult > 0);
Salida de consola:
2 ^ 3
00000000000000000000000000000000000000000000000000000000001000
2 ^ 3 + 2 ^ 63
00100000000000000000000000000000000000000000000000000000001000
2 ^ 3 y (2 ^ 3 + 2 ^ 63)
00000000000000000000000000000000000000000000000000000000001000
¿Correlación entre val1 y val2?
cierto
Javascript representa todos los números como números de punto flotante IEEE 754 de doble precisión de 64 bits (consulte la especificación ECMAscript , sección 8.5). Todos los enteros positivos de hasta 2 ^ 53 se pueden codificar con precisión. Los enteros más grandes obtienen sus bits menos significativos recortados. Esto deja la pregunta de cómo se puede representar un entero de 64 bits en Javascript: el tipo de datos del número nativo claramente no puede representar con precisión un int de 64 bits.
Lo siguiente ilustra esto. Aunque parece que JavaScript puede analizar números hexadecimales que representan números de 64 bits, la representación numérica subyacente no contiene 64 bits. Prueba lo siguiente en tu navegador:
<html>
<head>
<script language="javascript">
function showPrecisionLimits() {
document.getElementById("r50").innerHTML = 0x0004000000000001 - 0x0004000000000000;
document.getElementById("r51").innerHTML = 0x0008000000000001 - 0x0008000000000000;
document.getElementById("r52").innerHTML = 0x0010000000000001 - 0x0010000000000000;
document.getElementById("r53").innerHTML = 0x0020000000000001 - 0x0020000000000000;
document.getElementById("r54").innerHTML = 0x0040000000000001 - 0x0040000000000000;
}
</script>
</head>
<body onload="showPrecisionLimits()">
<p>(2^50+1) - (2^50) = <span id="r50"></span></p>
<p>(2^51+1) - (2^51) = <span id="r51"></span></p>
<p>(2^52+1) - (2^52) = <span id="r52"></span></p>
<p>(2^53+1) - (2^53) = <span id="r53"></span></p>
<p>(2^54+1) - (2^54) = <span id="r54"></span></p>
</body>
</html>
En Firefox, Chrome e IE obtengo lo siguiente. Si los números se almacenaron en toda su gloria de 64 bits, el resultado debería haber sido 1 para todas las sustracciones. En su lugar, puede ver cómo se pierde la diferencia entre 2 ^ 53 + 1 y 2 ^ 53.
(2^50+1) - (2^50) = 1
(2^51+1) - (2^51) = 1
(2^52+1) - (2^52) = 1
(2^53+1) - (2^53) = 0
(2^54+1) - (2^54) = 0
¿Entonces que puedes hacer?
Si elige representar un entero de 64 bits como dos números de 32 bits, entonces aplicar un AND a nivel de bits es tan simple como aplicar 2 AND a nivel de bits, a las ''palabras'' de 32 bits bajas y altas.
Por ejemplo:
var a = [ 0x0000ffff, 0xffff0000 ];
var b = [ 0x00ffff00, 0x00ffff00 ];
var c = [ a[0] & b[0], a[1] & b[1] ];
document.body.innerHTML = c[0].toString(16) + ":" + c[1].toString(16);
te atrapa
ff00:ff0000
La biblioteca de cierre tiene goog.math.Long
con un método add()
bitwise.