

| Language or processor | Left | Right |
|---|---|---|
| ActionScript 3,Java,JavaScript,Python,PHP,Ruby,C,C++,[1]D,C#,Go,Julia, Rust (signed types only)[2], Swift (signed types only)[note 1] | << | >> |
| Ada | Shift_Left[3] | Shift_Right_Arithmetic |
| Kotlin | shl | shr |
| Fortran | SHIFTL | SHIFTA[note 2] |
| Standard ML | << | ~>> |
| Verilog | <<< | >>>[note 3] |
| OpenVMS macro language | @[note 4] | |
| Scheme | arithmetic-shift[note 5] | |
| Common Lisp | ash | |
| OCaml | lsl | asr |
| Haskell | Data.Bits.shift[note 6] | |
| VHDL | sla[note 7] | sra |
| Assembly:Z80 | SLA[5] | SRA |
| Assembly:x86 | SAL | SAR |
| Assembly:68k | ASL | ASR |
| Assembly:RISC-V | sll,slli[6] | sra,srai |
Incomputer programming, anarithmetic shift is ashift operator, sometimes termed asigned shift (though it is not restricted to signed operands). The two basic types are thearithmetic left shift and thearithmetic right shift. Forbinary numbers it is abitwise operation that shifts all of the bits of its operand; every bit in the operand is simply moved a given number of bit positions, and the vacant bit-positions are filled in. Instead of being filled with all 0s, as inlogical shift, when shifting to the right, the leftmost bit (usually thesign bit in signedinteger representations) is replicated to fill in all the vacant positions (this is a kind ofsign extension).
Some authors prefer the termssticky right-shift andzero-fill right-shift for arithmetic and logical shifts respectively.[7]
Arithmetic shifts can be useful as efficient ways to perform multiplication or division of signed integers by powers of two. Shifting left byn bits on a signed or unsigned binary number has the effect of multiplying it by 2n. Shifting right byn bits on atwo's complementsigned binary number has the effect of dividing it by 2n, but it always rounds down (towards negative infinity). This is different from the way rounding is usually done in signed integer division (which rounds towards 0). This discrepancy has led to bugs in a number of compilers.[8]
For example, in thex86 instruction set, the SAR instruction (arithmetic right shift) divides a signed number by apower of two, rounding towards negative infinity.[9] However, the IDIV instruction (signed divide) divides a signed number, rounding towards zero. So a SAR instruction cannot be substituted for an IDIV by power of two instruction nor vice versa.
The formal definition of an arithmetic shift, fromFederal Standard 1037C is that it is:
A shift, applied to the representation of a number in a fixedradix numeration system and in afixed-point representation system, and in which only the characters representing the fixed-point part of the number are moved. An arithmetic shift is usually equivalent to multiplying the number by a positive or a negative integral power of the radix, except for the effect of any rounding; compare thelogical shift with the arithmetic shift, especially in the case offloating-point representation.
An important word in the FS 1073C definition is "usually".
However, arithmeticright shifts are major traps for the unwary, specifically in treating rounding of negative integers. For example, in the usualtwo's complement representation of negative integers, −1 is represented as all 1's. For an 8-bit signed integer this is 1111 1111. An arithmetic right-shift by 1 (or 2, 3, ..., 7) yields 1111 1111 again, which is still −1. This corresponds to rounding down (towards negative infinity), but is not the usual convention for division.
It is frequently stated that arithmetic right shifts are equivalent todivision by a (positive, integral) power of the radix (e.g., a division by a power of 2 for binary numbers), and hence that division by a power of the radix can be optimized by implementing it as an arithmetic right shift. (A shifter is much simpler than a divider. On most processors, shift instructions will execute faster than division instructions.) Large number of 1960s and 1970s programming handbooks, manuals, and other specifications from companies and institutions such asDEC,IBM,Data General, andANSI make such incorrect statements[10][page needed].
Logical right shifts are equivalent to division by a power of the radix (usually 2) only for positive or unsigned numbers. Arithmetic right shifts are equivalent to logical right shifts for positive signed numbers. Arithmetic right shifts for negative numbers in N's complement (usuallytwo's complement) is roughly equivalent to division by a power of the radix (usually 2), where for odd numbers rounding downwards is applied (not towards 0 as usually expected).
Arithmetic right shifts for negative numbers are equivalent to division using rounding towards 0 inones' complement representation of signed numbers as was used by some historic computers, but this is no longer in general use.
The (1999) ISO standard for the programming languageC defines the right shift operator in terms of divisions by powers of 2.[11] Because of the above-stated non-equivalence, the standard explicitly excludes from that definition the right shifts of signed numbers that have negative values. It does not specify the behaviour of the right shift operator in such circumstances, but instead requires each individual C compiler to define the behaviour of shifting negative values right.[note 8]
Like C, C++ had an implementation-defined right shift for signed integers untilC++20. Starting in the C++20 standard, right shift of a signed integer is defined to be an arithmetic shift.[13]
In applications where consistent rounding down is desired, arithmetic right shifts for signed values are useful. An example is indownscaling raster coordinates by a power of two, which maintains even spacing. For example, right shift by 1 sends 0, 1, 2, 3, 4, 5, ... to 0, 0, 1, 1, 2, 2, ..., and −1, −2, −3, −4, ... to −1, −1, −2, −2, ..., maintaining even spacing as −2, −2, −1, −1, 0, 0, 1, 1, 2, 2, ... In contrast, integer division with rounding towards zero sends −1, 0, and 1 all to 0 (3 points instead of 2), yielding −2, −1, −1, 0, 0, 0, 1, 1, 2, 2, ... instead, which is irregular at 0.
>> operator in C and C++ is not necessarily an arithmetic shift. Usually it is only an arithmetic shift if used with a signed integer type on its left-hand side. If it is used on an unsigned integer type instead, it will be alogical shift.arithmetic-shift can be both left and right shift, depending on the second operand, very similar to the OpenVMS macro language, although R6RS Scheme adds both-right and-left variants.Bits class from Haskell'sData.Bits module defines bothshift taking a signed argument andshiftL/shiftR taking unsigned arguments. These areisomorphic; for new definitions the programmer need provide only one of the two forms and the other form will be automatically defined in terms of the provided one.
This article incorporatespublic domain material fromFederal Standard 1037C.General Services Administration. Archived fromthe original on 2022-01-22.
{{cite book}}:|work= ignored (help)