Aritmeettinen siirto - Arithmetic shift
| 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
-
^ 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.
>> - ^ 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.
- ^ 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.)
-
^ Kaaviossa
arithmetic-shiftvoi olla sekä vasen että oikea siirto toisesta operandista riippuen, hyvin samanlainen kuin OpenVMS -makrokieli, vaikka R6RS -järjestelmä lisää molemmat-rightja-leftvariantit. -
^ 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 - ^ 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.
- ^ 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
Tämä artikkeli sisältää julkista aineistoa päässä General Services Administration asiakirjan "Federal Standard 1037C" .
- Knuth, Donald (1969). Tietokoneohjelmoinnin taide , osa 2 - Seminumeeriset algoritmit . Lukeminen, massa: Addison-Wesley. s. 169–170.
- Steele, Guy L. (marraskuu 1977). "Aritmeettista siirtoa pidetään haitallisena" . ACM SIGPLAN -ilmoitusten arkisto . New York: ACM Press. 12 (11): 61–69. doi : 10.1145/956641.956647 . HDL : 1721,1 / 6090 .
- "3.7.1 Aritmeettinen siirtotoiminto" . VAX MACRO ja käyttöohjeiden käyttöopas . HP OpenVMS -järjestelmien dokumentaatio . Hewlett-Packardin kehitysyhtiö. Huhtikuu 2001. Arkistoitu alkuperäisestä 2011-08-08.
-
"Ohjelmointikielet - C". ISO/IEC 9899: 1999. Kansainvälinen standardointijärjestö . 1999. Cite journal vaatii
|journal=( apua ) - Hyde, Randall (1996-09-26). "KUUSTA LUKU: 80x86 OHJEET (osa 3)". KOKONAISKIELEN OHJELMOINNIN TAIDE . Arkistoitu alkuperäisestä 23.11.2007 . Haettu 28.11.2007 .
- "C -toteutus" . GCC käsikirja . Free Software Foundation . 2008.