Ich habe gelesen , was sind bitweise Operatoren? Ich weiß also, was bitweise Operatoren sind, aber ich bin mir immer noch nicht sicher , wie man sie verwenden könnte. Kann jemand Beispiele aus der Praxis anbieten, wo ein bitweiser Operator in JavaScript nützlich wäre?
Vielen Dank.
Bearbeiten:
Beim Durchsuchen der jQuery-Quelle habe ich einige Stellen gefunden, an denen bitweise Operatoren verwendet werden, zum Beispiel: (nur der Operator &)
// 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;
Ich stark verwenden Bitoperatoren für numerische convertions in Produktion Skripte, denn manchmal sind sie viel schneller als ihre
Math
oderparseInt
Äquivalente.Der Preis, den ich zahlen muss, ist die Lesbarkeit des Codes . Also benutze ich normalerweise
Math
in der Entwicklung und bitweise in der Produktion.Auf jsperf.com finden Sie einige Performance-Tricks .
Wie Sie sehen können, optimieren Browser nicht
Math.ceil
undparseInt
seit Jahren, daher gehe ich davon aus, dass bitweise auch schneller und kürzer sein wird, um Dinge in Zukunft zu erledigen .Einige weiterführende Literatur zu SO ...
Bonus: Spickzettel für
| 0
: eine einfache und schnelle Möglichkeit, etwas in eine Ganzzahl umzuwandeln:( 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;
und etwas Magie für mich:
3 | '0px' === 3;
quelle
'use strict'; Function.prototype.valueOf = function() {return 2;};console.log(( (function(){})|0 ) === 0);
und Sie werden sehen, dass Ihre letzten beiden Beispiele nicht korrekt sind und so weiter.In JavaScript können Sie eine doppelte bitweise Negation (
~~n
) als Ersatz fürMath.floor(n)
(wennn
eine positive Zahl ist) oderparseInt(n, 10)
(auch wenn sien
negativ ist) verwenden.n|n
undn&n
liefern immer die gleichen Ergebnisse wie~~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
Eine einzelne bitweise Negation (
~
) wird berechnet-(parseInt(n, 10) + 1)
, sodass zwei bitweise Negationen zurückgegeben werden-(-(parseInt(n, 10) + 1) + 1)
.Es ist anzumerken, dass von diesen drei Alternativen
n|n
die schnellste zu sein scheint .Update: Genauere Benchmarks hier: http://jsperf.com/rounding-numbers-down
(Wie auf Strangest Language Feature veröffentlicht )
quelle
n << 0;
ist jetzt am schnellsten auf V8.n | 0;
ist sehr dicht dahinter und ist was ich benutze.n >>> 0
?wetMop = n|0; // bitwise version of Math.floor
Ein Beispiel aus dem wirklichen Leben :
^
bitweises XOR alsI/O
ToglerWird wie verwendet
value ^= 1
, ändert sich bei jedem Aufruf desvalue
to0, 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>
quelle
Angesichts der Fortschritte, die Javascript macht (insbesondere bei NodeJS, die eine serverseitige Programmierung mit Js ermöglichen), gibt es in JS immer komplexeren Code. Hier sind einige Fälle, in denen ich bitweise Operatoren verwendet habe:
IP-Adressoperationen:
//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));
Hinweis: Dies ist C-Code, aber JS ist fast identisch
Schauen Sie sich dazu den Wikipedia-Eintrag an
quelle
Um festzustellen, ob eine Zahl ungerade ist:
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
Schneller als Modul - dort einsetzen, wo Leistung wirklich zählt!
quelle
Einige andere Beispiele für die Verwendung von bitweise nicht und doppelt bitweise nicht:
Bodenbetrieb
~~2.5 // 2 ~~2.1 // 2 ~~(-2.5) // -2
Überprüfen Sie, ob indexOf -1 zurückgegeben hat oder nicht
var foo = 'abc'; !~foo.indexOf('bar'); // true
quelle
Sie können sie zum Umdrehen eines Booleschen Werts verwenden:
var foo = 1; var bar = 0; alert(foo ^= 1); alert(bar ^= 1);
Dies ist allerdings etwas albern und zum größten Teil haben bitweise Operatoren nicht viele Anwendungen in Javascript.
quelle
var arr = ['abc', 'xyz']
Verärgert zu schreiben
if (arr.indexOf('abc') > -1) { // 'abc' is in arr } if (arr.indexOf('def') === -1) { // 'def' is not in arr }
um zu überprüfen, ob sich etwas in einem Array befindet?
Sie können den bitweisen Operator folgendermaßen verwenden
~
:if (~arr.indexOf('abc')) { // 'abc' is in arr } if (! ~arr.indexOf('def')) { // 'def' is not in arr }
quelle
arr.includes
kann auch seit ES2016Bitmasken .
Wird häufig in JS-Ereignissen verwendet.
quelle
Ich habe es einmal für ein Berechtigungs-Widget verwendet . Dateiberechtigungen unter Unix sind eine Bitmaske. Um sie zu analysieren, müssen Sie Bitoperationen verwenden.
quelle
Ich verwende sie, um drei Zahlen zu 1 zu reduzieren, um mehrdimensionale Arrays in einem Uint16Array zu speichern . Hier ist ein Ausschnitt aus einem Voxel-Spiel, das ich entwickle:
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]);
quelle
65535
Wert, warum die 5 und 10 in(x << 5) + (z << 10)
Diese Antwort enthält Erklärungen zu Marks Antwort .
Durch Lesen dieser Erklärungen und Ausführen des Code-Snippets kann eine Idee gewonnen werden.
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) */
quelle
Sie scheinen sehr nützlich zu sein, wenn Sie mit Hex-Werten und Bits arbeiten. Da 4 Bits 0 bis F darstellen können.
1111 = F 1111 1111 = FF.
quelle
Beispiel mit Node.js
Angenommen, Sie hätten eine Datei (multiply.js) mit diesen Inhalten, könnten Sie ausführen
`node multiply <number> <number>`
und eine Ausgabe erhalten, die mit der Verwendung des Multiplikationsoperators für dieselben zwei Zahlen übereinstimmt. Die in der
Mulitply
Funktion ablaufende Bitverschiebung ist ein Beispiel dafür, wie die Bitmaske, die eine Zahl darstellt, verwendet wird, um Bits in einer anderen Zahl für schnelle Operationen umzudrehen.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);
quelle
Ich habe gerade diese Frage gefunden, um zu bestätigen, ob der bitweise
AND
Operator auch&
in Javascript ist.Da Sie nach einem Beispiel gefragt haben:
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'); } }); }
Es füllt den Status von Schaltflächen mit jQuery, wenn ein Bitmaskenwert eines ausgeblendeten Felds angegeben wird:
none
=0
user
=1
administrator
=2
user
+administrator
=3
quelle