ECMAScriptin bityt operaattorit

Bittisiirtymäoperaattorit toimivat numeron pohjakerroksella (eli numeron 32 bittisellä esityksellä).

Uudelleenluku luvut

ECMAScript-määrät ovat kahta tyyppiä, nimittäin merkkitunnisteita (sallitaan positiiviset ja negatiiviset luvut) ja merkitöntä (sallitaan vain positiiviset luvut). Kaikki ECMAScript-alkio-merkit ovat oletuksena merkkitunnisteita, mitä tämä tarkoittaa?

Merkkimäärät käyttävät 31 sijaa luvun arvon esittämiseen, 32. sija edustaa luvun merkkiä, 0 positiiviselle ja 1 negatiiviselle. Arvoalue vaihtelee -2147483648:sta 2147483647:een.

Binäärisessä muodossa olevia merkkimääriä voidaan tallentaa kahdella eri tavalla, toinen käytetään positiivisten lukujen tallentamiseen ja toinen negatiivisten lukujen tallentamiseen. Positiiviset luvut tallennetaan totta binäärisessä muodossa, jokainen 31. sija edustaa 2:n potenssia, alkaen ensimmäisestä sijasta (sija 0), joka edustaa 20Toinen sija (sija 1) edustaa 21Ei käytettyjä sijoja täytetään nollilla, eli ne jätetään huomiotta. Esimerkiksi, kuvassa näkyy luvun 18 esitys.

32-bittinen merkkijono esitetty symbolisena kokonaisluvuna

18:n binääriesitys käyttää vain ensimmäisiä 5 sijoja, jotka ovat tämän luvun tehokkaita sijoja. Kun numero muunnetaan binäärisenä merkkijonona, näet tehokkaita sijoja:

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

Tämä koodi tulostaa vain "10010", ei 18:n 32-bittinen esitys. Muita sijoja ei ole tärkeä, koska vain ensimmäiset 5 sijoja riittää määrittämään tämän desimaalisen arvon. Kuten kuvassa näkyy:

5-bittinen merkkijono esitetty kokonaisluvuna 18

Negatiiviset luvut tallennetaan myös binäärikoodina, mutta niiden muoto on binäärikoodin lisäys. Lasketaan luvun binäärikoodin lisäyksen vaiheet kolmessa vaiheessa:

  1. Määritä luvun ei-negatiivisen version binäärimuoto (esimerkiksi, laskiaksesi -18 binäärikoodin, on ensin määritettävä 18 binäärimuoto)
  2. Lasketaan binääriinvertti, mikä tarkoittaa, että 0 korvataan 1:llä ja 1 korvataan 0:lla
  3. Lisätään 1 binääriinverttiin

Jotta voidaan määrittää -18 binäärimuoto, on ensin saatava 18 binäärimuoto seuraavasti:

0000 0000 0000 0000 0000 0000 0001 0010

Seuraavaksi lasketaan binääriinvertti seuraavasti:

1111 1111 1111 1111 1111 1111 1110 1101

Lopuksi lisätään 1 binääriinverttiin seuraavasti:

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

Näin ollen -18 binäärimuoto on 1111 1111 1111 1111 1111 1111 1110 1110. Muista, että käsiteltäessä merkittyjä kokonaislukuja kehittäjät eivät voi käyttää bittiä 31.

On mielenkiintoista, että ECMAScript ei näytä negatiivisten kokonaislukujen binäärikoodia binäärikoodin muodossa, vaan esittää ne negatiivisena merkin kanssa lisätyn numeerisen absoluttisen binäärikoodin muodossa. Esimerkiksi:

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

Tämä koodi tulostaa "-10010", ei binäärikoodin, jotta vältetään bittin 31 käyttö. ECMAScript käsittelee kokonaislukuja yksinkertaisella tavalla, jotta kehittäjät eivät tarvitse huolehtia niiden käytöstä.

Toisaalta merkitsemättömät kokonaisluvut käsittelevät viimeistä bittiä toisena bittinä. Tässä järjestelmässä 32. bitti ei ole merkinnän symboli, vaan arvo 231Tämän ylimääräisen bittin vuoksi merkitsemättömien kokonaislukujen arvo-ala on 0-4294967295. Vähemmän kuin 2147483647 kokonaislukujen osalta merkitsemättömät kokonaisluvut näyttävät samalta kuin merkittömät kokonaisluvut, mutta suuremmat kuin 2147483647 kokonaisluvut vaativat bittin 31 (merkittömässä kokonaisluvussa tämä bitti on aina 0).

Kun merkitsemätön kokonaisluku muunnetaan merkkijonoksi, palautetaan vain niiden kelvolliset bittit.

Huomioitavaa:Kaikki kokonaislukulauseet tallennetaan oletusarvoisesti merkittömänä kokonaislukuna. Vain ECMAScriptin bit-operaattorit voivat luoda merkitsemättömiä kokonaislukuja.

Bit-operaatio NOT

Bit-operaatio NOT ilmaistaan kieltona (~), ja se on yksi ECMAScriptin harvoista binäärimatrikkelilaskennan kanssa liittyvistä operaattoreista.

Bit-operaatio NOT on kolmivaiheinen prosessi:

  1. Muunna laskennalliset luvut 32-bittisiksi numeroksi
  2. Muunna binääriset luvut niiden binäärisiksi käänteiskoodiksi
  3. Muunna binääriset luvut liukulukuiksi

Esimerkiksi:

var iNum1 = 25;		// 25 on 00000000000000000000000000011001
var iNum2 = ~iNum1;	// Muunnetaan 11111111111111111111111111100110
alert(iNum2);		// Tulostaa "-26"

Bit-operaatio NOT on itse asiassa numeron negointi ja sitten vähennys 1, joten 25 muuttuu -26. Voimme myös käyttää seuraavaa menetelmää saadaksemme saman tuloksen:

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

Bit-operaatio AND

Bit-operaatio AND symboloidaan merkillä (&) ja suoritetaan suoraan numeron binäärisessä muodossa. Se tasapainottaa jokaisen numeron numeroydintä ja suorittaa AND-operaation samassa sijainnissa oleville kahdelle ydille seuraavien sääntöjen mukaisesti:

ensimmäisen numeron bitit toisen numeron bitit Tulos
1 1 1
1 0 0
0 1 0
0 0 0

Esimerkiksi, jotta suoritetaan 25 ja 3 AND-operaatio, koodi näyttää seuraavalta:

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

25 ja 3 suoritettu AND-operaatio antaa tuloksen 1. Miksi? Analysoidaan seuraavasti:

 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

Voimme nähdä, että 25 ja 3 -lukuissa vain yksi numeroydin (sijainti 0) sisältää arvon 1, joten muut ydintuotokset ovat 0, joten tuloksena on 1.

Bit-operaatio OR

Bit-operaatio OR symboloidaan merkillä (|) ja suoritetaan suoraan numeron binäärisessä muodossa. Laskennassa jokaiselle numerolle OR-operaattori käyttää seuraavia sääntöjä:

ensimmäisen numeron bitit toisen numeron bitit Tulos
1 1 1
1 0 1
0 1 1
0 0 0

Edelleen käyttäen AND-operaattoria käytettyä esimerkkiä, suoritetaan 25 ja 3 OR-operaatio, koodi seuraavasti:

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

25 ja 3 suoritettu OR-operaatio antaa tuloksen 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

Voimme nähdä, että kahdessa luvussa on yhteensä 4 numeroydintä, jotka sisältävät arvon 1, ja nämä ydintä siirretään tulokseen. Binäärikoodi 11011 on yhtä kuin 27.

Bit-operaatio XOR

Bit-operaatio XOR esitetään merkkinä (^), tietenkin, suoritetaan suoraan binäärimuodossa. XOR eronaan OR-operaatioon, palauttaa 1 vain, jos vain yksi bitistä on arvo 1. Totuustaulukko seuraavasti:

ensimmäisen numeron bitit toisen numeron bitit Tulos
1 1 0
1 0 1
0 1 1
0 0 0

Suoritetaan XOR-operaatio 25 ja 3 välillä, koodi seuraavasti:

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

25 ja 3 suoritetun XOR-opeerauksen tulos on 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

voidaan nähdä, että kahdessa numerossa on yhteensä 4 bitiä, joissa on arvo 1, ja nämä bitit siirtyvät tulokseen. Binäärikoodi 11010 on yhtä kuin 26.

Vasen siirtymä

Vasen siirtymäoperatori esitetään kahdella pienellä ympyrällä osoittimella (<<). Se siirtää luvun kaikki numerot vasemmalle annetun määrän sijaa. Esimerkiksi, kun numero 2 (binääri 10) siirretään vasemmalle 5 sijaa, tulos on 64 (binääri 1000000):

var iOld = 2;		// yhtä kuin binääri 10
var iNew = iOld << 5;	// yhtä kuin binääri 1000000 desimaalina 64

Huomioitavaa:Vasemmalla siirtymällä luvun oikealle puolelle jää 5 tyhjää tilaa. Vasen siirtymä täyttää nämä tyhjät tilat nollilla, jotta tulos on täydellinen 32-bittinen luku.

Luku 2 suorittaa vasemmalle siirtymäoperatiota

Huomioitavaa:Vasen siirtymä säilyttää luvun merkki-bitin. Esimerkiksi, jos -2 siirretään vasemmalle 5 sijaa, saadaan -64, ei 64. "Onko merkki-bit edelleen tallennettuna 32. numeroympyrässä?" Kyllä, mutta tämä tapahtuu ECMAScriptin taustalla, ja kehittäjät eivät voi suoraan käyttää 32. numeroympyrää. Vaikka negatiiviset luvut tulostetaan binäärisinä merkkijonoina, ne näytetään miinusmerkin muodossa (esimerkiksi, -2 näytetään -10.)

Symbolinen oikea siirtymä

Symbolinen oikea siirtymäoperatori esitetään kahdella ympyrällä osoittimella (>>). Se siirtää 32-bittisen luvun kaikki numerot kokonaisuudessaan oikealle, samalla säilyttäen luvun merkkiä (positiivinen tai negatiivinen). Symbolinen oikea siirtymäoperatori on täysin päinvastainen kuin vasen siirtymä. Esimerkiksi, kun 64 oikeasti siirretään 5 sijaa, se muuttuu 2:ksi:

var iOld = 64; // yhtä kuin binääri 1000000
var iNew = iOld >> 5; // yhtä kuin binääri 10 desimaalina 2

Samoin, siirrettäessä bittisiirtoja syntyy tyhjiä paikkoja. Tällä kertaa tyhjät paikat ovat numeron vasemmalla puolella, mutta merkkitunnin jälkeen. ECMAScript täyttää nämä tyhjät paikat merkkitunnin arvolla, luoden täydellisen luvun, kuten kuvassa näkyy:

Luku 64 suorittaa symbolista oikealle siirtymäoperatiota

Nollasivuista oikeanpuoleista siirtymisoperaattori

Nollasivuista oikeanpuoleista siirtymisoperaattori merkitään kolmella ylätunnilla (>>>), ja se siirtää merkkivapaiden 32-bittisten lukujen kaikki bittit kokonaisuudessaan oikealle.

Käytä esimerkistä merkkimäärän oikeanpuoleisesta siirtymisoperaattorista, jos 64 siirretään oikealle 5 sijaa, se muuttuu 2:ksi:

var iOld = 64; // yhtä kuin binääri 1000000
var iNew = iOld >>> 5; // yhtä kuin binääri 10 desimaalina 2

Negatiivisten lukujen tapauksessa tilanne on erilainen.

Nollasivuista oikeanpuoleista siirtymisoperaattori täyttää kaikki tyhjät paikat nollilla. Positiivisille luvuille tämä on sama kuin merkkimäärän oikeanpuoleinen siirtymisoperaattori, mutta negatiiviset luvut käsitellään positiivisina luvuina.

Koska nollasivuista oikeanpuoleista siirtymisoperaattorin tuloksena on 32-bittinen positiivinen luku, negatiivisten lukujen nollasivuista oikeanpuoleista siirtymisoperaattorin tuloksena on aina erittäin suuri luku. Esimerkiksi, jos -64 siirretään oikealle 5 sijaa, se tuottaa 134217726. Miten tämä tulos saadaan?

Tämä voidaan saavuttaa muuntamalla luku yksinkertaisesti merkkivapaa vastaavaan muotoon (vaikka luku itsessään on merkkimäärä), mikä voidaan saavuttaa seuraavalla koodilla:

var iUnsigned64 = -64 >>> 0;

Sitten, käytä Number-tyypin toString() -metodia saadaksesi sen todellisen bittipäivityksen, käytettynä peruslukuun 2:

alert(iUnsigned64.toString(2));

Tämä tuottaa 11111111111111111111111111000000, joka on merkkimäärän -64 binääripäivitysmerkintä, mutta se on yhtä suuri kuin merkkimäärän 4294967232.

Tästä syystä on oltava varovainen käyttäessäsi nollasivuista oikeanpuoleista siirtymisoperaattoria.