Aritmeettinen siirto - Arithmetic shift

Image
Binaariluvun oikea aritmeettinen siirto yhdellä. Merkittävimmän bitin tyhjä paikka täytetään kopiolla alkuperäisestä MSB: stä.
Image
Binääriluvun aritmeettinen siirto vasemmalla yhdellä. Vähiten merkitsevän bitin tyhjä paikka täytetään nollalla.
Aritmeettiset siirtooperaattorit eri ohjelmointikielillä ja prosessoreilla
Kieli tai prosessori Vasen Aivan
ActionScript 3, Java , JavaScript , Python , PHP , Ruby ;
C , C ++ , D , C# , Go , Julia , Swift (vain allekirjoitetut tyypit)
<< >>
Ada Shift_Left Shift_Right_Arithmetic
Kotlin shl shr
Vakio ML << ~>>
Verilog <<< >>>
OpenVMS makrokielellä @
Kaavio arithmetic-shift
Yhteinen Lisp ash
OCaml lsl asr
Haskell Data.Bits.shift
Kokoonpano, 68k ASL ASR
Kokoonpano, x86 SAL SAR
VHDL sla sra
RISC-V sll, slli sra, srai
Z80 SLA SRA

Vuonna ohjelmointi , An aritmeettinen muutos on siirtyminen operaattorin , joskus kutsutaan allekirjoitettu muutos (vaikka se ei rajoitu allekirjoitettu operandit). Kaksi perustyyppiä ovat aritmeettinen vasen siirto ja aritmeettinen oikea siirto . Sillä binääriluvut se on bittioperaatio että siirtymät kaikki bitit sen operandin; jokainen operandin bitti siirretään yksinkertaisesti tietty määrä bittikohtia ja tyhjät bittikohdat täytetään. Sen sijaan, että ne täytettäisiin kaikilla 0: lla, kuten loogisessa siirrossa , siirryttäessä oikealle, vasemmanpuoleisin bitti (yleensä allekirjoitusbitti allekirjoitetuissa kokonaislukuesityksissä) kopioidaan täyttämään kaikki avoimet paikat (tämä on eräänlainen merkkilaajennus ).

Jotkut kirjoittajat pitävät aritmeettisia ja loogisia siirtoja parempana termejä tahmea oikea siirto ja nollatäytön oikea siirto .

Aritmeettiset siirrot voivat olla hyödyllisiä tehokkaina keinoina suorittaa allekirjoitettujen kokonaislukujen kertominen tai jakaminen kahden teholla. Siirtyminen n bittiä vasemmalle allekirjoitetussa tai allekirjoittamattomassa binääriluvussa saa sen kertomalla 2 n: llä . Siirtäminen oikealle n bitillä kahden komplementin allekirjoittamalla binaariluvulla jakaa sen 2 n: llä , mutta se pyöristää aina alaspäin (kohti negatiivista ääretöntä). Tämä eroaa tavasta, jolla pyöristys tehdään yleensä allekirjoitettuun kokonaislukujakaumaan (joka pyöristää kohti 0). Tämä ero on johtanut virheisiin useissa kääntäjissä.

Esimerkiksi x86 -käskysarjassa SAR -käsky (aritmeettinen oikea siirto) jakaa allekirjoitetun luvun kahdella voimalla ja pyöristää negatiiviseen äärettömyyteen. IDIV -ohje (allekirjoitettu jako) jakaa kuitenkin allekirjoitetun luvun pyöristämällä kohti nollaa. Joten SAR -käskyä ei voida korvata IDIV: llä kahden käskyn voimalla eikä päinvastoin.

Muodollinen määritelmä

Aritmeettisen muutoksen virallinen määritelmä liittovaltion standardista 1037C on seuraava:

Siirto, jota sovelletaan luvun esittämiseen kiinteän radiksin numerointijärjestelmässä ja kiinteän pisteen esitysjärjestelmässä ja jossa siirretään vain numeron kiinteän pisteen osaa edustavia merkkejä. Aritmeettinen siirto vastaa yleensä luvun kertomista radiksin positiivisella tai negatiivisella integraaliteholla lukuun ottamatta pyöristyksen vaikutusta; vertaa loogista siirtoa aritmeettiseen siirtoon, etenkin liukulukuesityksen tapauksessa .

Tärkeä sana FS 1073C -määrityksessä on "yleensä".

Aritmeettisten ja loogisten vasemman siirtymien ja kertolaskujen vastaavuus

Aritmeettiset vasen siirtymät vastaavat kertomista radiksin (positiivisella, integraalisella) teholla (esim. Kertoimella 2: lla binaariluvuilla). Loogiset vasen siirtymät ovat myös vastaavia, lukuun ottamatta kertolaskua ja aritmeettisia siirtoja, jotka voivat laukaista aritmeettisen ylivuoton, kun taas loogiset siirtymät eivät.

Aritmeettisen oikean siirtymän ja jaon vastaavuus

Aritmeettiset oikeat siirtymät ovat kuitenkin tärkeitä ansoja varovaisille, erityisesti negatiivisten kokonaislukujen pyöristämisessä. Esimerkiksi tavanomaisessa kahden komplementin negatiivisen kokonaisluvun esityksessä −1 esitetään kaikilla 1: llä. 8-bittiselle allekirjoitetulle kokonaisluvulle tämä on 1111 1111. Aritmeettinen oikea siirto 1: llä (tai 2, 3, ..., 7) antaa jälleen 1111 1111, joka on edelleen -1. Tämä vastaa pyöristämistä alaspäin (kohti negatiivista ääretöntä), mutta se ei ole tavallinen jakautumissopimus.

Usein sanotaan, että aritmeettiset oikeat siirtymät vastaavat jakamista radiksin (positiivisella, integraalisella) teholla (esim. Jako kahdella teholla binaariluvuille), ja siksi että jako radiksin teholla voidaan optimoitu toteuttamalla se aritmeettisena oikeana siirtona. (Vaihdevipu on paljon yksinkertaisempi kuin jakaja. Useimmissa suorittimissa siirto -ohjeet suoritetaan nopeammin kuin jako -ohjeet.) Suuri määrä 1960- ja 1970 -lukujen ohjelmointioppaita, käsikirjoja ja muita eritelmiä yrityksiltä ja laitoksilta, kuten DEC , IBM , Data General ja ANSI antavat tällaisia ​​vääriä lausuntoja.

Loogiset oikeat siirtymät vastaavat jakamista radiksin teholla (yleensä 2) vain positiivisille tai allekirjoittamattomille numeroille. Aritmeettiset oikeat siirtymät vastaavat loogisia oikeita siirtoja positiivisille allekirjoitetuille numeroille. Aritmeettiset oikeat siirtymät negatiivisille numeroille N − 1: n komplementissa (yleensä kahden komplementti ) vastaavat suunnilleen jakoa radiksin teholla (yleensä 2), jossa parittomille numeroille käytetään pyöristämistä alaspäin (ei kohti nollaa, kuten yleensä odotetaan).

Negatiivisten lukujen aritmeettiset oikeat siirtymät vastaavat jakamista käyttäen pyöristämistä kohti nollaa allekirjoitettujen numeroiden komplementtiesityksessä , kuten jotkut historialliset tietokoneet käyttivät, mutta tämä ei ole enää yleisessä käytössä.

Ongelman käsittely ohjelmointikielillä

Ohjelmointikielen C (1999) ISO-standardi määrittelee oikean siirtooperaattorin jakamalla tehot 2: lla. Edellä mainitun vastaavuuden vuoksi standardi sulkee nimenomaisesti määritelmän ulkopuolelle oikeat siirtymät allekirjoitetuista numeroista, joilla on negatiiviset arvot. Se ei määritä oikean siirtooperaattorin käyttäytymistä tällaisissa olosuhteissa, vaan vaatii jokaista yksittäistä C -kääntäjää määrittämään negatiivisten arvojen siirtämisen oikein.

Sovellukset

Sovelluksissa, joissa halutaan johdonmukaista pyöristämistä alaspäin, aritmeettiset oikeat siirtymät allekirjoitetuille arvoille ovat hyödyllisiä. Esimerkki on rasterikoordinaattien pienentäminen kahden teholla, joka säilyttää tasaisen etäisyyden. Esimerkiksi oikea siirto 1: llä lähettää 0, 1, 2, 3, 4, 5, ... 0, 0, 1, 1, 2, 2, ... ja −1, −2, −3, −4, ... - −1, −1, −2, −2, ..., säilyttäen tasaisen etäisyyden −2, −2, −1, −1, 0, 0, 1, 1, 2, 2 , ... Sitä vastoin kokonaislukujako pyöristämällä kohti nollaa lähettää -1, 0 ja 1 kaikki 0: ksi (3 pistettä 2: n sijasta), jolloin tuloksena on -2, -1, -1, 0, 0, 0, 1, 1, 2, 2, ... sen sijaan, joka on epäsäännöllinen 0: ssa.

Huomautuksia

  1. ^ Operaattori C ja C ++ ei välttämättä aritmeettinen muutos. Yleensä se on vain aritmeettinen siirto, jos sitä käytetään allekirjoitettuun kokonaislukutyyppiin sen vasemmalla puolella. Jos sitä käytetään sen sijaan allekirjoittamattomalla kokonaislukutyypillä, se on looginen muutos. >>
  2. ^ Verilogin aritmeettinen oikean siirtymän operaattori suorittaa aritmeettisen siirron vain, jos ensimmäinen operandi on allekirjoitettu. Jos ensimmäinen operandi on allekirjoittamaton, operaattori todella tekee loogisen oikean siirron.
  3. ^ Vuonna OpenVMS- makrokielellä, onko aritmeettinen siirto vasemmalle tai oikealle määritetään, onko toinen operandi on positiivinen tai negatiivinen. Tämä on epätavallista. Useimmissa ohjelmointikielissä molemmilla suunnilla on erilliset operaattorit, operaattori määrittää suunnan, ja toinen operandi on epäsuorasti positiivinen. (Jotkut kielet, kuten Verilog, edellyttävät negatiivisten arvojen muuntamista allekirjoittamattomiksi positiivisiksi arvoiksi. Joillakin kielillä, kuten C ja C ++, ei ole määriteltyä toimintaa, jos käytetään negatiivisia arvoja.)
  4. ^ Kaaviossaarithmetic-shiftvoi olla sekä vasen että oikea siirto toisesta operandista riippuen, hyvin samanlainen kuin OpenVMS -makrokieli, vaikka R6RS -järjestelmä lisää molemmat-rightja-leftvariantit.
  5. ^ Luokan Haskell nmoduuli määrittelee sekäottamalla allekirjoitettu argumentin ja/ottamalla allekirjoittamattomia argumentteja. Nämä ovat isomorfisia ; uusia määritelmiä varten ohjelmoijan on annettava vain yksi kahdesta lomakkeesta ja toinen muoto määritetään automaattisesti annetun lomakkeen perusteella.BitsData.BitsshiftshiftLshiftR
  6. ^ VHDL -aritmeettinen vasen siirtotoiminto on epätavallinen. Sen sijaan, että täytettäisiin tuloksen LSB nollalla, se kopioi alkuperäisen LSB: n uuteen LSB: hen. Vaikka tämä on tarkka peilikuva aritmeettisesta oikeasta siirtymästä, se ei ole tavanomainen operaattorin määritelmä, eikä se vastaa kertomista 2: lla. VHDL 2008 -standardissa tämä outo käyttäytyminen jätettiin ennalleen (taaksepäin yhteensopivuuden vuoksi) ) argumenttityypeille, joilla ei ole pakotettua numeerista tulkintaa (esim. BIT_VECTOR), mutta SLA allekirjoittamattomille ja allekirjoitetuille argumenttityypeille käyttäytyy odotetulla tavalla (eli oikeimmat reunat on täytetty nollilla). VHDL: n siirtymisvasen looginen (SLL) -toiminto toteuttaa edellä mainitun "vakio" -aritmeettisen siirron.
  7. ^ C -standardin tarkoituksena ei ollut rajoittaa C -kieltä kummankaan tai kahden komplementti -arkkitehtuuriin. Tapauksissa, joissa komplementin ja kahden komplementin esitysten käyttäytyminen vaihtelee, kuten tämä, standardi vaatii yksittäisiä C -kääntäjiä dokumentoimaan kohdearkkitehtuuriensa käyttäytymisen. Esimerkiksi GNU-kääntäjäkokoelman (GCC) dokumentaatio dokumentoi sen käyttäytymisen käyttämällä merkkien laajennusta.

Viitteet

Viittaus

Käytetyt lähteet

Julkinen verkkotunnus Tämä artikkeli sisältää  julkista aineistoa päässä General Services Administration asiakirjan "Federal Standard 1037C" .