traduccion operadores bitwise javascript bitwise-operators

operadores - ¿Dónde usaría un operador bitwise en JavaScript?



bitwise translate (16)

Acabo de encontrar esta pregunta tratando de confirmar si el operador AND bit a bit también estaba & en Javascript.

Ya que pidió un ejemplo:

if ($(''input[id="user[privileges]"]'').length > 0) { $(''#privileges button'').each(function () { if (parseInt($(''input[id="user[privileges]"]'').val()) & parseInt($(this).attr(''value''))) { $(this).button(''toggle''); } }); }

Rellena el estado de los botones con jQuery dado un valor de máscara de bits de un campo oculto:

  • none = 0
  • user = 1
  • administrator = 2
  • user + administrator = 3

He leído ''¿qué son los operadores bit a bit?'' , así que sé qué son los operadores bit a bit, pero aún no tengo claro cómo se podrían usar. ¿Alguien puede ofrecer ejemplos reales de dónde un operador bit a bit sería útil en JavaScript?

Gracias.

Editar:

Acabo de profundizar en la fuente jQuery . He encontrado un par de lugares donde se utilizan operadores bit a bit, por ejemplo: (solo el operador &)

// Line 2756: event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); // Line 2101 var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;


Ejemplo:

Analiza el valor hexadecimal para obtener valores de color RGB.

var hex = ''ffaadd''; var rgb = parseInt(hex, 16); // rgb is 16755421 var red = (rgb >> 16) & 0xFF; // returns 255 var green = (rgb >> 8) & 0xFF; // 170 var blue = rgb & 0xFF; // 221


En JavaScript, puede usar una negación doble a nivel de bits ( ~~n ) como reemplazo de Math.floor(n) (si n es un número positivo) o parseInt(n, 10) (incluso si n es negativo). n|n y n&n siempre arrojan los mismos resultados que ~~n .

var n = Math.PI; n; // 3.141592653589793 Math.floor(n); // 3 parseInt(n, 10); // 3 ~~n; // 3 n|n; // 3 n&n; // 3 // ~~n works as a replacement for parseInt() with negative numbers… ~~(-n); // -3 (-n)|(-n); // -3 (-n)&(-n); // -3 parseInt(-n, 10); // -3 // …although it doesn’t replace Math.floor() for negative numbers Math.floor(-n); // -4

Una sola negación a nivel de bit ( ~ ) calcula -(parseInt(n, 10) + 1) , por lo que regresarán dos negaciones en modo bit -(-(parseInt(n, 10) + 1) + 1) .

Cabe señalar que de estas tres alternativas, n|n parece ser el más rápido .

Actualización: puntos de referencia más precisos aquí: http://jsperf.com/rounding-numbers-down

(Según publicado en la característica de idioma más extraño )


Esta respuesta contiene explicaciones de share de share .

Al leer estas explicaciones y ejecutar el fragmento de código, se puede obtener una idea.

var hex = ''ffaadd''; var rgb = parseInt(hex, 16); // rgb value is 16755421 in decimal = 111111111010101011011101 in binary = total 24 bits var red = (rgb >> 16) & 0xFF; // returns 255 var green = (rgb >> 8) & 0xFF; // returns 170 var blue = rgb & 0xFF; // returns 221 // HOW IS IT // There are two bitwise operation as named SHIFTING and AND operations. // SHIFTING is an operation the bits are shifted toward given direction by adding 0 (zero) bit for vacated bit fields. // AND is an operation which is the same with multiplying in Math. For instance, if 9th bit of the given first bit-set is 0 // and 9th bit of the given second bit-set is 1, the new value will be 0 because of 0 x 1 = 0 in math. // 0xFF (000000000000000011111111 in binary) - used for to evaluate only last 8 bits of a given another bit-set by performing bitwise AND (&) operation. // The count of bits is 24 and the first 16 bits of 0xFF value consist of zero (0) value. Rest of bit-set consists of one (1) value. console.log("0xFF /t/t/t/t: ", 0xFF) // 111111111010101011011101 -> bits of rgb variable // 000000000000000011111111 -> 255 after (rgb >> 16) shifting operation // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits) // 000000000000000011111111 -> result bits after performing bitwise & operation console.log("Red - (rgb >> 16) & 0xFF /t: ", (rgb >> 16) & 0xFF) // used for to evaluate the first 8 bits // 111111111010101011011101 -> bits of rgb variable // 000000001111111110101010 -> 65450 -> ''ffaa'' // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits) // 000000000000000010101010 -> result bits after performing bitwise & operation // calculation -> 000000001111111110101010 & 000000000000000011111111 = 000000000000000010101010 = 170 in decimal = ''aa'' in hex-decimal console.log("Green - (rgb >> 8) & 0xFF /t: ", (rgb >> 8) & 0xFF) // used for to evaluate the middle 8 bits // 111111111010101011011101 -> ''ffaadd'' // 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits) // 000000000000000011011101 -> result bits after performing bitwise & operation // calculation -> 111111111010101011011101 & 000000000000000011111111 = 221 in decimal = ''dd'' in hex-decimal console.log("Blue - rgb & 0xFF /t/t: ", rgb & 0xFF) // // used for to evaluate the last 8 bits. console.log("It means that `FFAADD` hex-decimal value specifies the same color with rgb(255, 170, 221)") /* console.log(red) console.log(green) console.log(blue) */


Lo he usado una vez para un widget de permisos . Los permisos de archivos en Unix son una máscara de bits, por lo que para analizarlos, debe usar operaciones de bits.


Los estoy usando para aplanar tres números en 1 como una forma de almacenar matrices multidimensionales en un Uint16Array . Aquí hay un fragmento de un juego de vóxel que estoy desarrollando:

function Chunk() { this._blocks = new Uint16Array(32768); this._networkUpdates = []; } Chunk.prototype.getBlock = function(x, y, z) { return this._blocks[y + (x << 5) + (z << 10)]; }; Chunk.prototype.setBlock = function(x, y, z, value) { this._blocks[y + (x << 5) + (z << 10)] = value; this._networkUpdates.push(value + (y << 15) + (x << 20) + (z << 25)); }; Chunk.prototype.getUpdates = function() { return this._networkUpdates; }; Chunk.prototype.processUpdate = function(update) { // this._blocks[Math.floor(update / 65536)] = update % 65536; this._blocks[update >> 16] = update & 65535; }; var chunk = new Chunk(); chunk.setBlock(10, 5, 4); alert(chunk.getBlock(10, 5, 4)); alert(chunk.getUpdates()[0]);


Para saber si un número es impar:

function isOdd(number) { return !!(number & 1); } isOdd(1); // true, 1 is odd isOdd(2); // false, 2 is not odd isOdd(357); // true, 357 is odd

Más rápido que el módulo: ¡utilícelo donde el rendimiento realmente cuenta!


Parecen ser muy útiles cuando trabajas con valores hexadecimales y bits. Dado que 4 bits pueden representar de 0 a F.

1111 = F 1111 1111 = FF.


Pocos otros ejemplos de cómo usar bitwise not y double bitwise no:

Operación de piso

~~2.5 // 2 ~~2.1 // 2 ~~(-2.5) // -2

Verifique si indexOf devolvió -1 o no

var foo = ''abc''; !~foo.indexOf(''bar''); // true


Puedes usarlos para voltear un valor booleano:

var foo = 1; var bar = 0; alert(foo ^= 1); alert(bar ^= 1);

Esto es un poco tonto y en su mayor parte los operadores bit a bit no tienen muchas aplicaciones en Javascript.


Teniendo en cuenta los avances que está haciendo JavaScript (especialmente con nodejs que permite la programación del lado del servidor con js), hay cada vez más código complejo en JS. Aquí hay un par de instancias donde he usado operadores bit a bit:

  • Operaciones de dirección IP:

    //computes the broadcast address based on the mask and a host address broadcast = (ip & mask) | (mask ^ 0xFFFFFFFF) //converts a number to an ip adress sprintf(ip, "%i.%i.%i.%i", ((ip_int >> 24) & 0x000000FF), ((ip_int >> 16) & 0x000000FF), ((ip_int >> 8) & 0x000000FF), ( ip_int & 0x000000FF));

Nota: este es el código C, pero JS es casi idéntico

  • Los algoritmos CRC los usan mucho

Echa un vistazo a la entrada de Wikipedia en este

  • Operaciones de resolución de pantalla

Un example vida real :

^ XOR bit a bit como un toggler de I/O

Usado como value ^= 1 cambiará en cada llamada el value a 0, 1, 0, 1 ...

function toggle(evt) { evt.target.IO ^= 1; // Bitwise XOR as 1/0 toggler evt.target.textContent = evt.target.IO ? "ON" : "OFF"; // Unleash your ideas } [...document.querySelectorAll("button")].forEach( el => el.addEventListener("click", toggle) );

<button>OFF</button> <button>OFF</button> <button>OFF</button>


Utilizo mucho los operadores bit a bit para las conversiones numéricas en scripts de producción, porque a veces son mucho más rápidos que sus equivalentes Math o de parseInt .

El precio que tengo que pagar es la legibilidad del código . Por lo tanto, generalmente uso Math en desarrollo y bitwise en producción.

Puede encontrar algunos trucos de rendimiento en jsperf.com .

Como puede ver, los navegadores no optimizan Math.ceil y parseInt durante años, por lo que predigo bitwise será una manera más rápida y más corta de hacer cosas en furure también .

Algunas lecturas adicionales sobre SO ...

Bono: hoja de trucos para | 0 | 0 : una forma fácil y rápida de convertir cualquier cosa a entero:

( 3|0 ) === 3; // it does not change integers ( 3.3|0 ) === 3; // it casts off the fractional part in fractionalal numbers ( 3.8|0 ) === 3; // it does not round, but exactly casts off the fractional part ( -3.3|0 ) === -3; // including negative fractional numbers ( -3.8|0 ) === -3; // which have Math.floor(-3.3) == Math.floor(-3.8) == -4 ( "3"|0 ) === 3; // strings with numbers are typecast to integers ( "3.8"|0 ) === 3; // during this the fractional part is cast off too ( "-3.8"|0 ) === -3; // including negative fractional numbers ( NaN|0 ) === 0; // NaN is typecast to 0 ( Infinity|0 ) === 0; // the typecast to 0 occurs with the Infinity ( -Infinity|0 ) === 0; // and with -Infinity ( null|0 ) === 0; // and with null, ( (void 0)|0 ) === 0; // and with undefined ( []|0 ) === 0; // and with an empty array ( [3]|0 ) === 3; // but an array with one number is typecast to number ( [-3.8]|0 ) === -3; // including the cast off of the fractional part ( [" -3.8 "]|0 ) === -3; // including the typecast of strings to numbers ( [-3.8, 22]|0 ) === 0 // but an Array with several numbers is typecast to 0 ( {}|0 ) === 0; // an empty object is typecast to 0 ( {''2'':''3''}|0 ) === 0; // or a not empty object ( (function(){})|0 ) === 0; // an empty function is typecast to 0 too ( (function(){ return 3;})|0 ) === 0;

y algo de magia para mí:

3 | ''0px'' === 3;


Bitmasks .

Usado ampliamente, por ejemplo, en eventos JS.


Ejemplo usando Node.js

Presumiendo que tenía un archivo (llamado multiply.js) con estos contenidos, podría ejecutar

`node multiply <number> <number>`

y obtener un resultado consistente con el uso del operador de multiplicación en los mismos dos números. El cambio de bit en la función Mulitply es un ejemplo de cómo tomar la máscara de bits que representa un número y usarla para voltear bits en otro número para operaciones rápidas.

var a, b, input = process.argv.slice(2); var printUsage = function() { console.log(''USAGE:''); console.log('' node multiply <number> <number>''); } if(input[0] === ''--help'') {+ printUsage(); process.exit(0); } if(input.length !== 2) { printUsage(); process.exit(9); } if(isNaN(+input[0]) || isNaN(+input[1])) { printUsage(); process.exit(9); } // Okay, safe to proceed a = parseInt(input[0]), b = parseInt(input[1]); var Multiply = function(a,b) { var x = a, y = b, z = 0; while( x > 0 ) { if(x % 2 === 1) { z = z + y; } y = y << 1; x = x >> 1; } return z; } var result = Multiply(a,b); console.log(result);


var arr = [''abc'', ''xyz'']

Molesto de escribir

if (arr.indexOf(''abc'') > -1) { // ''abc'' is in arr } if (arr.indexOf(''def'') === -1) { // ''def'' is not in arr }

para verificar si hay algo dentro de una matriz?

Puede usar el operador bit a bit ~ así:

if (~arr.indexOf(''abc'')) { // ''abc'' is in arr } if (! ~arr.indexOf(''def'')) { // ''def'' is not in arr }