ECMAScript bitoperatorer

Bitoperatorer utför operationer på numrets grundnivå (dvs. de 32 bitar som representerar numret).

Genomgå heltal igen

ECMAScript heltal har två typer, nämligen teckenbärande heltal (som tillåter både positiva och negativa tal) och otal (som endast tillåter positiva tal). I ECMAScript är alla heltalskonkreta värden som standard teckenbärande heltal, vilket innebär vad?

Teckenbärande heltal används 31 bitar för att representera heltalens värde, med den 32:onde biten för att representera heltalens tecken, 0 för positiva tal och 1 för negativa tal. Värdespannet är från -2147483648 till 2147483647.

Det finns två olika sätt att lagra teckenbärande heltal, ett för positiva tal och ett för negativa tal. Positiva tal lagras i en riktig binär form, där varje bit av de första 31 bitarna representerar 2:ans potens, börjar från den första positionen (bit 0) och representerar 20Den andra positionen (bit 1) representerar 21Oanvända bitar fylls med 0, vilket innebär att de ignoreras. Till exempel visar följande bild 18:s representation.

32-bit binära representationer av teckenbärande heltal

18:s binära version använder bara de första 5 siffrorna, som är de effektiva bitarna. Konvertera numret till en binär sträng för att se effektiva bitar:

var iNum = 18;
alert(iNum.toString(2));	// utmatar "10010"

Detta kod utmatar bara "10010", inte 18:s 32-bit representation. Andra siffror är inte viktiga eftersom endast de första 5 siffrorna behövs för att fastställa decimalvärdet. Som visas i följande bild:

5-bit binära representationer av heltal 18

Negativa tal lagras också som binära koder, men i form av binära komplement. Det finns tre steg för att beräkna binära komplement för ett tal:

  1. Bestäm binära presentationen av den icke-negative versionen av det här talet (t.ex. för att beräkna binära komplement för -18 måste man först bestämma binära presentationen av 18)
  2. Få binära omvända tecken, vilket innebär att man byter 0 mot 1 och 1 mot 0
  3. Lägg till 1 till binära omvända tecken

För att bestämma binära presentationen av -18 måste man först få binära presentationen av 18, som visas nedan:

0000 0000 0000 0000 0000 0000 0001 0010

Nästa steg är att beräkna binära omvända tecken, som visas nedan:

1111 1111 1111 1111 1111 1111 1110 1101

Till slut, lägg till 1 till binära omvända tecken, som visas nedan:

1111 1111 1111 1111 1111 1111 1110 1101
                                      1
---------------------------------------
1111 1111 1111 1111 1111 1111 1110 1110

Så är binära presentationen av -18 1111 1111 1111 1111 1111 1111 1110 1110. Kom ihåg att utvecklare kan inte få åtkomst till bit 31 när de hanterar teckenbärande heltal.

Det är intressant att ECMAScript inte visar binära komplement när negativa heltal konverteras till binära strängar, utan visar dem som en negativ teckenbärande binär kod med negativtecken framför. Till exempel:

var iNum = -18;
alert(iNum.toString(2));	// skriver ut "-10010"

Denna kod skriver ut "-10010", inte binära komplement, för att undvika åtkomst till bit 31. För enkelhetens skull hanterar ECMAScript heltal på ett enkelt sätt så att utvecklare inte behöver bry sig om deras användning.

Å andra sidan behandlar oteckenbärande heltal det sista biten som en annan bitplats. I detta schema representerar den 32:e biten inte tecknet på talet utan värdet 2.31På grund av denna extra bit är intervallet för oteckenbärande heltal 0 till 4294967295. För heltal mindre än 2147483647 verkar oteckenbärande heltal lika som teckenbärande heltal, medan heltal större än 2147483647 måste använda bit 31 (i teckenbärande heltal är denna bit alltid 0).

När en oteckenbärande heltal konverteras till en sträng returneras bara de effektiva bitarna.

Observera:Alla heltalskonstanter lagras som teckenbärande heltal som standard. Det är bara ECMAScripts bitoperatorer som kan skapa oteckenbärande heltal.

Bitoperator NOT

Bitoperator NOT representeras med tillämpningsbeteckningen (~) och är en av de få binära aritmetiska operatorerna i ECMAScript.

Bitoperatorn NOT är ett tristegsbehandlingsförfarande:

  1. Konvertera beräkningsnumret till 32-bitars siffra
  2. Konvertera binär siffra till dess binära invers
  3. Konvertera binär siffra till flyttal

Till exempel:

var iNum1 = 25;		//25 är lika med 00000000000000000000000000011001
var iNum2 = ~iNum1;	//Konvertera till 11111111111111111111111111100110
alert(iNum2);		//Output "-26"

Bitoperatorn NOT är i grunden att ta det negativa av ett nummer och sedan subtrahera 1, så att 25 blir -26. Detta kan också uppnås med följande metod:

var iNum1 = 25;
var iNum2 = -iNum1 -1;
alert(iNum2);	//Output -26

Bitoperatorn AND

Bitoperatorn AND representeras av summateckenet (&) och utför direkt beräkning på binär form av siffror. Det rätar upp varje siffra i varje siffra och använder följande regler för att utföra AND-operation på två siffror på samma plats:

Bitarna i det första talet Bitarna i den andra talet Resultat
1 1 1
1 0 0
0 1 0
0 0 0

Till exempel, för att utföra AND-operationen mellan siffrorna 25 och 3, koden är som följer:

var iResult = 25 & 3;
alert(iResult);	//Output "1"

Resultatet av AND-operationen mellan 25 och 3 är 1. Varför? Analys som följer:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
AND = 0000 0000 0000 0000 0000 0000 0000 0001

Det kan ses att i 25 och 3 finns det bara en nummersystem (bit 0) som innehåller 1, så andra nummersystem genererar alla 0, så resultatet är 1.

Bitoperatorn OR

Bitoperatorn OR representeras av symbolen (|) och utför direkt beräkning på binär form av siffror. När man beräknar varje siffra använder OR-operatorn följande regler:

Bitarna i det första talet Bitarna i den andra talet Resultat
1 1 1
1 0 1
0 1 1
0 0 0

För att använda exempel med AND-operatorn, utför OR-operationen mellan 25 och 3, koden är som följer:

var iResult = 25 | 3;
alert(iResult);	//Output "27"

Resultatet av OR-operationen mellan 25 och 3 är 27:

25 = 0000 0000 0000 0000 0000 0000 0001 1001
 3 = 0000 0000 0000 0000 0000 0000 0000 0011
--------------------------------------------
OR = 0000 0000 0000 0000 0000 0000 0001 1011

Det kan ses att i de två siffrorna finns det 4 nummersystem som innehåller 1, dessa nummersystem överförs till resultatet. Binärkoden 11011 är lika med 27.

Bitoperator XOR

Bitoperatorn XOR representeras av tecknet (^), naturligtvis också direkt på binär form. XOR skiljer sig från OR, eftersom den bara returnerar 1 när en bit innehåller 1. Sanningsfunktionen ser ut som följande:

Bitarna i det första talet Bitarna i den andra talet Resultat
1 1 0
1 0 1
0 1 1
0 0 0

För XOR-operationen mellan 25 och 3, se kod nedan:

var iResult = 25 ^ 3;
alert(iResult);	// skriver ut "26"

Resultatet av XOR-operationen mellan 25 och 3 är 26:

 25 = 0000 0000 0000 0000 0000 0000 0001 1001
  3 = 0000 0000 0000 0000 0000 0000 0000 0011
---------------------------------------------
XOR = 0000 0000 0000 0000 0000 0000 0001 1010

Det kan ses att i två tal finns det 4 bitar som innehåller 1, och dessa bitar överförs till resultatet. Binärcode 11010 liknar 26.

Den vänstra flyttoperationen

Den vänstra flyttoperationen representeras av två mindre tecken (<<). Den flyttar alla bitar i ett tal till vänster med den angivna mängden. Till exempel, om talet 2 (liknar binär 10) flyttas 5 bitar till vänster, blir resultatet 64 (liknar binär 1000000):

var iOld = 2;		// liknar binär 10
var iNew = iOld << 5;	// liknar binär 1000000 decimal 64

Observera:När man vänsterflyttar bitar, blir det 5 tomma platser till höger om talet. Vänsterflyttningen fyller dessa platser med 0, så att resultatet blir ett helt 32-bitstal.

Numer 2 genomför vänsterflyttning

Observera:Den vänstra flyttoperationen bevarar teckensbiten. Till exempel, om -2 flyttas 5 bitar till vänster, blir resultatet -64, inte 64. "Finns tecknet fortfarande i den 32:onde biten?" Ja, men detta sker bakom ECMAScript, och utvecklaren kan inte direkt få tillgång till den 32:onde biten. Även om ett negativt tal visas som en binärsträng, visas det också som ett negativt tecken (t.ex. -2 visas som -10).

Den teckenbärande högerflyttoperationen

Den teckenbärande högerflyttoperator representeras av två större tecken (>>). Den flyttar alla bitar i ett 32-bitstal till höger, samtidigt som den bevarar tecknet (plus eller minus). Den teckenbärande högerflyttoperator är tvärtom den vänstra flyttoperatorn. Till exempel, om 64 flyttas 5 bitar till höger, blir det 2:

var iOld = 64; // lika med binära 1000000
var iNew = iOld >> 5; // lika med binära 10 tio decimal 2

Också, efter att ha flyttat bitarna skapas det tomma platser. Denna gång är dessa tomma platser på vänster sida av talet, men efter symbolpositionen. ECMAScript fyller dessa tomma platser med symbolpositionens värde för att skapa ett fullständigt tal, som visas i följande bild:

Numer 64 genomför teckenbärande högerflyttning

Osignerad högerflyttning

Den osignerade högerflyttningen representeras av tre större än-tecken (>>>), och den flyttar alla bitar av ett osignerat 32-bitars tal till höger. För positiva tal är resultatet av den osignerade högerflyttningen lika med den teckensatta högerflyttningen.

Med hjälp av ett exempel med den teckensatta högerflyttningen, om du högerflyttar 64 med 5 bitar, blir det 2:

var iOld = 64; // lika med binära 1000000
var iNew = iOld >>> 5; // lika med binära 10 tio decimal 2

För negativa tal är situationen annorlunda.

Den osignerade högerflyttningen fyller alla tomma platser med 0. För positiva tal är detta lika med den teckensatta högerflyttningen, medan negativa tal behandlas som positiva tal.

Eftersom resultatet av den osignerade högerflyttningen är ett 32-bitars positivt tal, får den negativa talets osignerade högerflyttning alltid ett mycket stort tal. Till exempel, om du högerflyttar -64 med 5 bitar, får du 134217726. Hur får man detta resultat?

För att uppnå detta behöver du konvertera numret till en osignerad ekvivalent form (även om numret själv är teckensatt), vilket kan uppnås genom följande kod:

var iUnsigned64 = -64 >>> 0;

Därefter, använd Number-objektets toString() för att få dess riktiga bitpresentation, med basen 2:

alert(iUnsigned64.toString(2));

Detta genererar 11111111111111111111111111000000, som är det binära komplementet av det teckensatta talet -64, men det är lika med det osignerade talet 4294967232.

Därför måste du vara försiktig när du använder den osignerade högerflyttoperatorn.