Arithmetic shift: Difference between revisions

From Wikipedia, the free encyclopedia
Jump to navigation Jump to search
imported>Headbomb
Altered journal. | Use this tool. Report bugs. | #UCB_Gadget
imported>MsMissing
add See also section
 
(One intermediate revision by one other user not shown)
Line 9: Line 9:
! Language or processor !! Left !! Right
! Language or processor !! Left !! Right
|-
|-
| style="max-width:195px" | [[ActionScript]] 3, [[Java (programming language)|Java]], [[JavaScript]], [[Python (programming language)|Python]], [[PHP]], [[Ruby (programming language)|Ruby]], [[C (programming language)|C]], [[C++]],<ref>{{Cite web|url=https://tour.dlang.org/tour/en/gems/bit-manipulation|title=Bit manipulation - Dlang Tour|website=tour.dlang.org|access-date=2019-06-23}}</ref>[[D (programming language)|D]], [[C_Sharp_(programming_language)|C#]], [[Go (programming language)|Go]], [[Julia (programming language)|Julia]],<br />[[Rust (programming language)|Rust]] (signed types only)<ref>{{Cite web|title=Operator Expressions: Arithmetic and Logical Binary Operators|url=https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators|access-date=2022-11-13|website=doc.rust-lang.org}}</ref>,<br />[[Swift (programming language)|Swift]] (signed types only)<ref group="note">The <code> >> </code> 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 a ''logical'' shift.</ref>||<code> << </code> || <code> >> </code>
| style="max-width:195px" | [[ActionScript]] 3, [[Java (programming language)|Java]], [[JavaScript]], [[Python (programming language)|Python]], [[PHP]], [[Ruby (programming language)|Ruby]], [[C (programming language)|C]], [[C++]],<ref>{{Cite web|url=https://tour.dlang.org/tour/en/gems/bit-manipulation|title=Bit manipulation - Dlang Tour|website=tour.dlang.org|access-date=2019-06-23}}</ref>[[D (programming language)|D]], [[C Sharp (programming language)|C#]], [[Go (programming language)|Go]], [[Julia (programming language)|Julia]],<br/>[[Rust (programming language)|Rust]] (signed types only),<ref>{{Cite web|title=Operator Expressions: Arithmetic and Logical Binary Operators|url=https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators|access-date=2022-11-13|website=doc.rust-lang.org}}</ref><br/>[[Swift (programming language)|Swift]] (signed types only)<ref group="note">The <code> >> </code> 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 a ''logical'' shift.</ref>||<code> << </code> || <code> >> </code>
|-
|-
| [[Ada (programming language)|Ada]] || <code> Shift_Left </code><ref>{{Cite web|url=https://www.adaic.org/resources/add_content/standards/12aarm/html/AA-B-2.html|title=Annotated Ada 2012 Reference Manual}}</ref> || <code> Shift_Right_Arithmetic </code>
| [[Ada (programming language)|Ada]] || <code> Shift_Left </code><ref>{{Cite web|url=https://www.adaic.org/resources/add_content/standards/12aarm/html/AA-B-2.html|title=Annotated Ada 2012 Reference Manual}}</ref> || <code> Shift_Right_Arithmetic </code>
|-
|-
| [[Kotlin (programming language)|Kotlin]] || <code> shl </code> || <code> shr </code>
| [[Kotlin]] || <code> shl </code> || <code> shr </code>
|-
|-
| [[Fortran]] || <code> SHIFTL </code> || <code> SHIFTA </code><ref group="note">Fortran 2008.</ref>
| [[Fortran]] || <code> SHIFTL </code> || <code> SHIFTA </code><ref group="note">Fortran 2008.</ref>
Line 19: Line 19:
| [[Standard ML]] || <code> << </code> || <code> ~>> </code>
| [[Standard ML]] || <code> << </code> || <code> ~>> </code>
|-
|-
| [[Verilog]] || <code> <<< </code> || <code> >>> </code><ref group="note">The Verilog arithmetic right shift operator only actually performs an arithmetic shift if the first operand is signed. If the first operand is unsigned, the operator actually performs a ''logical'' right shift.</ref>
| [[Verilog]] || <code> <<< </code> || <code> >>> </code><ref group="note">The Verilog arithmetic right shift operator only actually performs an arithmetic shift if the first operand is signed. If the first operand is unsigned, the operator actually performs a ''logical'' right shift.</ref>
|-
|-
| [[OpenVMS]] macro language
| [[OpenVMS]] macro language
Line 32: Line 32:
| [[OCaml]] || <code>lsl</code> || <code>asr</code>
| [[OCaml]] || <code>lsl</code> || <code>asr</code>
|-
|-
| [[Haskell (programming language)|Haskell]]
| [[Haskell]]
| colspan="2" align="center" | <code>Data.Bits.shift</code>{{#tag:ref|The <code>Bits</code> class from Haskell's <code>Data.Bits</code> module defines both <code>shift</code> taking a signed argument and <code>shiftL</code>/<code>shiftR</code> taking unsigned arguments. These are [[isomorphic]]; 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.|group="note"}}
| colspan="2" align="center" | <code>Data.Bits.shift</code>{{#tag:ref|The <code>Bits</code> class from Haskell's <code>Data.Bits</code> module defines both <code>shift</code> taking a signed argument and <code>shiftL</code>/<code>shiftR</code> taking unsigned arguments. These are [[isomorphic]]; 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.|group="note"}}
|-
|-
| [[VHDL]] || <code>sla</code><ref group="note">The VHDL arithmetic left shift operator is unusual. Instead of filling the LSB of the result with zero, it copies the original LSB into the new LSB. While this is an exact mirror image of the arithmetic right shift, it is not the conventional definition of the operator, and is not equivalent to multiplication by a power of 2. In the VHDL 2008 standard this strange behavior was left unchanged (for backward compatibility) for argument types that do not have forced numeric interpretation (e.g., BIT_VECTOR) but 'SLA' for ''unsigned'' and ''signed'' argument types behaves in the expected way (i.e., rightmost positions are filled with zeros). VHDL's shift left logical (SLL) function does implement the aforementioned 'standard' arithmetic shift.</ref> || <code>sra</code>
| [[VHDL]] || <code>sla</code><ref group="note">The VHDL arithmetic left shift operator is unusual. Instead of filling the LSB of the result with zero, it copies the original LSB into the new LSB. While this is an exact mirror image of the arithmetic right shift, it is not the conventional definition of the operator, and is not equivalent to multiplication by a power of 2. In the VHDL 2008 standard this strange behavior was left unchanged (for backward compatibility) for argument types that do not have forced numeric interpretation (e.g., BIT_VECTOR) but 'SLA' for ''unsigned'' and ''signed'' argument types behaves in the expected way (i.e., rightmost positions are filled with zeros). VHDL's shift left logical (SLL) function does implement the aforementioned 'standard' arithmetic shift.</ref> || <code>sra</code>
|-
|-
| Assembly: [[Z80]] || <code>SLA</code><ref>{{Cite web|url=http://www.z80.info/z80syntx.htm#SLA|title=Z80 Assembler Syntax}}</ref> || <code>SRA</code>
| Assembly: [[Z80]] || <code>SLA</code><ref>{{Cite web|url=http://www.z80.info/z80syntx.htm#SLA|title=Z80 Assembler Syntax}}</ref> || <code>SRA</code>
Line 45: Line 45:
| Assembly: [[RISC-V]] || <code>sll</code>, <code>slli</code><ref>{{Cite web|url=https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf |archive-url=https://ghostarchive.org/archive/20221009/https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf |archive-date=2022-10-09 |url-status=live|date=2019-12-13|access-date=2021-08-07|title=The RISC-V Instruction Set Manual, Volume I: Unprivileged ISA|website=[[GitHub]] |pages=18–20}}</ref> || <code>sra</code>, <code>srai</code>
| Assembly: [[RISC-V]] || <code>sll</code>, <code>slli</code><ref>{{Cite web|url=https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf |archive-url=https://ghostarchive.org/archive/20221009/https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf |archive-date=2022-10-09 |url-status=live|date=2019-12-13|access-date=2021-08-07|title=The RISC-V Instruction Set Manual, Volume I: Unprivileged ISA|website=[[GitHub]] |pages=18–20}}</ref> || <code>sra</code>, <code>srai</code>
|}
|}
In [[computer programming]], an '''arithmetic shift''' is a [[Bitwise_operation#Bit_shifts|shift operator]], sometimes termed a '''signed shift''' (though it is not restricted to signed operands). The two basic types are the '''arithmetic left shift''' and the '''arithmetic right shift'''. For [[binary numeral system|binary number]]s it is a [[bitwise 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 in [[logical shift]], when shifting to the right, the leftmost bit (usually the [[sign bit]] in signed integer representations) is replicated to fill in all the vacant positions (this is a kind of [[sign extension]]).
In [[computer programming]], an '''arithmetic shift''' is a [[Bitwise operation#Bit shifts|shift operator]], sometimes termed a '''signed shift''' (though it is not restricted to signed operands). The two basic types are the '''arithmetic left shift''' and the '''arithmetic right shift'''. For [[binary numeral system|binary number]]s it is a [[bitwise 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 in [[logical shift]], when shifting to the right, the leftmost bit (usually the [[sign bit]] in signed [[integer]] representations) is replicated to fill in all the vacant positions (this is a kind of [[sign extension]]).


Some authors prefer the terms ''sticky right-shift'' and ''zero-fill right-shift'' for arithmetic and logical shifts respectively.<ref>
Some authors prefer the terms ''sticky right-shift'' and ''zero-fill right-shift'' for arithmetic and logical shifts respectively.<ref>
Line 55: Line 55:
</ref>
</ref>


Arithmetic shifts can be useful as efficient ways to perform multiplication or division of signed integers by powers of two. Shifting left by ''n'' bits on a signed or unsigned binary number has the effect of multiplying it by 2<sup>''n''</sup>. Shifting right by ''n'' bits on a [[two's complement]] ''signed'' binary number has the effect of dividing it by 2<sup>''n''</sup>, 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.<ref>{{cite web|last=Steele Jr|first=Guy|title=Arithmetic Shifting Considered Harmful|url=http://dspace.mit.edu/bitstream/handle/1721.1/6090/AIM-378.pdf |archive-url=https://ghostarchive.org/archive/20221009/http://dspace.mit.edu/bitstream/handle/1721.1/6090/AIM-378.pdf |archive-date=2022-10-09 |url-status=live|publisher=MIT AI Lab|access-date=20 May 2013}}</ref>
Arithmetic shifts can be useful as efficient ways to perform multiplication or division of signed integers by powers of two. Shifting left by ''n'' bits on a signed or unsigned binary number has the effect of multiplying it by 2<sup>''n''</sup>. Shifting right by ''n'' bits on a [[two's complement]] ''signed'' binary number has the effect of dividing it by 2<sup>''n''</sup>, 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.<ref>{{cite web|last=Steele|first=Guy Jr.|author-link=Guy L. Steele Jr.|title=Arithmetic Shifting Considered Harmful|url=http://dspace.mit.edu/bitstream/handle/1721.1/6090/AIM-378.pdf|publisher=MIT AI Lab|url-status=live|archive-url=https://ghostarchive.org/archive/20221009/http://dspace.mit.edu/bitstream/handle/1721.1/6090/AIM-378.pdf|archive-date=2022-10-09|access-date=20 May 2013}}</ref>


For example, in the [[x86 instruction listings|x86 instruction set]], the SAR instruction (arithmetic right shift) divides a signed number by a power of two, rounding towards negative infinity.{{sfn|Hyde|1996|loc=§ 6.6.2.2 SAR}} 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.
For example, in the [[x86 instruction listings|x86 instruction set]], the SAR instruction (arithmetic right shift) divides a signed number by a [[power of two]], rounding towards negative infinity.{{sfn|Hyde|1996|loc=§ 6.6.2.2 SAR}} 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.


== Formal definition ==
== Formal definition ==
Line 78: Line 78:
The (1999) ISO standard for the programming language [[C (programming language)|C]] defines the right shift operator in terms of divisions by powers of 2.{{sfn|ISOIEC9899|1999|loc=§ 6.5.7 Bitwise shift operators}} 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.{{#tag:ref|The C standard was intended to not restrict the C language to either ones' complement or two's complement architectures.  In cases where the behaviours of ones' complement and two's complement representations differ, such as this, the standard requires individual C compilers to document the behaviour of their target architectures.  The documentation for [[GNU Compiler Collection]] (GCC), for example, documents its behaviour as employing sign-extension.{{sfn|FSF|2008|loc=§ 4.5 Integers implementation}}|group="note"}}
The (1999) ISO standard for the programming language [[C (programming language)|C]] defines the right shift operator in terms of divisions by powers of 2.{{sfn|ISOIEC9899|1999|loc=§ 6.5.7 Bitwise shift operators}} 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.{{#tag:ref|The C standard was intended to not restrict the C language to either ones' complement or two's complement architectures.  In cases where the behaviours of ones' complement and two's complement representations differ, such as this, the standard requires individual C compilers to document the behaviour of their target architectures.  The documentation for [[GNU Compiler Collection]] (GCC), for example, documents its behaviour as employing sign-extension.{{sfn|FSF|2008|loc=§ 4.5 Integers implementation}}|group="note"}}


Like C, C++ had an implementation-defined right shift for signed integers until C++20. Starting in the C++20 standard, right shift of a signed integer is defined to be an arithmetic shift.{{sfn|ISOCPP20|2020|loc=§ 7.6.7 Shift operators}}
Like C, C++ had an implementation-defined right shift for signed integers until [[C++20]]. Starting in the C++20 standard, right shift of a signed integer is defined to be an arithmetic shift.{{sfn|ISOCPP20|2020|loc=§ 7.6.7 Shift operators}}


== Applications ==
== Applications ==
In applications where consistent rounding down is desired, arithmetic right shifts for signed values are useful. An example is in [[downscaling]] 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.
In applications where consistent rounding down is desired, arithmetic right shifts for signed values are useful. An example is in [[downscaling]] 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.
== See also ==
* [[Bitwise operation]]
* [[Logical shift]]


== Notes ==
== Notes ==
Line 89: Line 94:


=== Cross-reference ===
=== Cross-reference ===
{{Reflist|30em}}
{{Reflist}}


=== Sources used ===
=== Sources used ===
{{FS1037C}}
{{FS1037C}}
{{Refbegin}}
{{Refbegin}}
* {{cite book|first=Donald|last=Knuth|title=[[The Art of Computer Programming]], Volume 2 &mdash; Seminumerical algorithms|pages=169&ndash;170|location=Reading, Mass.|publisher=Addison-Wesley|year=1969|author-link=Donald Knuth}}
* {{cite book|last=Knuth|first=Donald|author-link=Donald Knuth|year=1969|title=[[The Art of Computer Programming]]: Seminumerical algorithms|volume=2|pages=169–170|location=Reading, Massachusetts|publisher=Addison-Wesley}}
* {{cite journal|title=Arithmetic shifting considered harmful|journal= ACM SIGPLAN Notices|volume=12|issue=11|date=November 1977|pages=61&ndash;69|first=Guy L.|last=Steele|publisher=ACM Press|location=New York|doi=10.1145/956641.956647|url=http://www.dtic.mil/get-tr-doc/pdf?AD=ADA031883|archive-url=https://web.archive.org/web/20170922201035/http://www.dtic.mil/get-tr-doc/pdf?AD=ADA031883|url-status=dead|archive-date=September 22, 2017|hdl=1721.1/6090|s2cid=15420308 |hdl-access=free}}
* {{cite journal|last=Steele|first=Guy L.|author-link=Guy L. Steele Jr.|date=November 1977|title=Arithmetic shifting considered harmful|journal= ACM SIGPLAN Notices|volume=12|issue=11|pages=61–69|publisher=ACM Press|location=New York|doi=10.1145/956641.956647|url=http://www.dtic.mil/get-tr-doc/pdf?AD=ADA031883|archive-url=https://web.archive.org/web/20170922201035/http://www.dtic.mil/get-tr-doc/pdf?AD=ADA031883|url-status=dead|archive-date=September 22, 2017|hdl=1721.1/6090|s2cid=15420308 |hdl-access=free}}
* {{cite book |ref=CITEREFHP2001|chapter-url=http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_002.html#8_arithmeticshiftoperator |work=HP OpenVMS Systems Documentation|title=VAX MACRO and Instruction Set Reference Manual |chapter=3.7.1 Arithmetic Shift Operator|publisher=Hewlett-Packard Development Company|date=April 2001 |archive-url=https://web.archive.org/web/20110808085326/http://h71000.www7.hp.com/doc/73final/4515/4515pro_002.html#8_arithmeticshiftoperator |archive-date=2011-08-08}}
* {{cite book|date=April 2001|ref=CITEREFHP2001|chapter-url=http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_002.html#8_arithmeticshiftoperator|chapter=3.7.1 Arithmetic Shift Operator|title=VAX MACRO and Instruction Set Reference Manual|series=HP OpenVMS Systems Documentation|publisher=Hewlett-Packard Development Company|archive-url=https://web.archive.org/web/20110808085326/http://h71000.www7.hp.com/doc/73final/4515/4515pro_002.html#8_arithmeticshiftoperator |archive-date=2011-08-08}}
* {{Cite book |ref=CITEREFISOIEC98991999|title=Programming languages &mdash; C|publisher=[[International Organization for Standardization]]|year=1999|version=ISO/IEC 9899:1999}}
* {{Cite book |ref=CITEREFISOIEC98991999|title=Programming languages – C|publisher=[[International Organization for Standardization]]|year=1999|version=ISO/IEC 9899:1999}}
* {{cite book|chapter=CHAPTER SIX: THE 80x86 INSTRUCTION SET (Part 3)|date=1996-09-26|title=The Art of ASSEMBLY LANGUAGE PROGRAMMING|first=Randall|last=Hyde|url=http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-3.html#HEADING3-120|access-date=2007-11-28|archive-url=https://web.archive.org/web/20071123223102/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-3.html#HEADING3-120|archive-date=2007-11-23|url-status=dead}}
* {{cite book|chapter=Chapter Six: The 80x86 Instruction Set (Part 3)|date=1996-09-26|title=the Art of Assembly Language Programming|first=Randall|last=Hyde|url=http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-3.html#HEADING3-120|access-date=2007-11-28|archive-url=https://web.archive.org/web/20071123223102/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/Chapter_6/CH06-3.html#HEADING3-120|archive-date=2007-11-23|url-status=dead}}
* {{cite web|ref=CITEREFFSF2008|year=2008|publisher=[[Free Software Foundation]]|url=https://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Integers-implementation.html#Integers-implementation|work=GCC manual|title=C Implementation}}
* {{cite web|ref=CITEREFFSF2008|year=2008|publisher=[[Free Software Foundation]]|url=https://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Integers-implementation.html#Integers-implementation|work=GCC manual|title=C Implementation}}
* {{cite web|ref={{harvid|ISOCPP20|2020}} |year=2020|publisher=International Organization for Standardization|title = ISO/IEC 14882:2020(E) – Programming Language C++|url = https://isocpp.org/files/papers/N4860.pdf}}
* {{cite web|ref={{harvid|ISOCPP20|2020}} |year=2020|publisher=International Organization for Standardization|title=ISO/IEC 14882:2020(E) – Programming Language C++|url=https://isocpp.org/files/papers/N4860.pdf}}
{{refend}}
{{Refend}}


{{DEFAULTSORT:Arithmetic Shift}}
{{DEFAULTSORT:Arithmetic Shift}}
[[Category:Binary arithmetic]]
[[Category:Binary arithmetic]]
[[Category:Operators (programming)]]
[[Category:Operators (programming)]]
[[Category:Programming language comparisons]]
<!-- Hidden categories below -->
[[Category:Articles with example Ada code]]
[[Category:Articles with example C code]]
[[Category:Articles with example C++ code]]
[[Category:Articles with example C Sharp code]]
[[Category:Articles with example Fortran code]]
[[Category:Articles with example Haskell code]]
[[Category:Articles with example Java code]]
[[Category:Articles with example JavaScript code]]
[[Category:Articles with example Julia code]]
[[Category:Articles with example Lisp (programming language) code]]
[[Category:Articles with example OCaml code]]
[[Category:Articles with example PHP code]]
[[Category:Articles with example Python (programming language) code]]
[[Category:Articles with example Rust code]]
[[Category:Articles with example Swift code]]

Latest revision as of 22:28, 26 May 2026

Template:Short description

File:Rotate right arithmetically.svg
A right arithmetic shift of a binary number by 1. The empty position in the most significant bit is filled with a copy of the original MSB.
File:Rotate left logically.svg
A left arithmetic shift of a binary number by 1. The empty position in the least significant bit is filled with a zero.
Arithmetic shift operators in various programming languages and processors
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[4] SRA
Assembly: x86 SAL SAR
Assembly: 68k ASL ASR
Assembly: RISC-V sll, slli[5] sra, srai

In computer programming, an arithmetic shift is a shift operator, sometimes termed a signed shift (though it is not restricted to signed operands). The two basic types are the arithmetic left shift and the arithmetic right shift. For binary numbers it is a bitwise 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 in logical shift, when shifting to the right, the leftmost bit (usually the sign bit in signed integer representations) is replicated to fill in all the vacant positions (this is a kind of sign extension).

Some authors prefer the terms sticky right-shift and zero-fill right-shift for arithmetic and logical shifts respectively.[6]

Arithmetic shifts can be useful as efficient ways to perform multiplication or division of signed integers by powers of two. Shifting left by n bits on a signed or unsigned binary number has the effect of multiplying it by 2n. Shifting right by n bits on a two's complement signed 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.[7]

For example, in the x86 instruction set, the SAR instruction (arithmetic right shift) divides a signed number by a power of two, rounding towards negative infinity.Script error: No such module "Footnotes".Script error: No such module "Check for unknown parameters". 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.

Formal definition

The formal definition of an arithmetic shift, from Federal Standard 1037C is that it is:

<templatestyles src="Template:Blockquote/styles.css" />

A shift, applied to the representation of a number in a fixed radix numeration system and in a fixed-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 the logical shift with the arithmetic shift, especially in the case of floating-point representation.

Script error: No such module "Check for unknown parameters".

An important word in the FS 1073C definition is "usually".

Non-equivalence of arithmetic right shift and division

However, arithmetic right shifts are major traps for the unwary, specifically in treating rounding of negative integers. For example, in the usual two'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 to division 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 as DEC, IBM, Data General, and ANSI make such incorrect statementsScript error: No such module "Footnotes".Script error: No such module "Check for unknown parameters".Script error: No such module "Unsubst"..

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 (usually two'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 in ones' complement representation of signed numbers as was used by some historic computers, but this is no longer in general use.

Handling the issue in programming languages

The (1999) ISO standard for the programming language C defines the right shift operator in terms of divisions by powers of 2.Script error: No such module "Footnotes".Script error: No such module "Check for unknown parameters". 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 until C++20. Starting in the C++20 standard, right shift of a signed integer is defined to be an arithmetic shift.Script error: No such module "Footnotes".Script error: No such module "Check for unknown parameters".

Applications

In applications where consistent rounding down is desired, arithmetic right shifts for signed values are useful. An example is in downscaling 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.

See also

Notes

  1. ↑ The >> 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 a logical shift.
  2. ↑ Fortran 2008.
  3. ↑ The Verilog arithmetic right shift operator only actually performs an arithmetic shift if the first operand is signed. If the first operand is unsigned, the operator actually performs a logical right shift.
  4. ↑ In the OpenVMS macro language, whether an arithmetic shift is left or right is determined by whether the second operand is positive or negative. This is unusual. In most programming languages the two directions have distinct operators, with the operator specifying the direction, and the second operand is implicitly positive. (Some languages, such as Verilog, require that negative values be converted to unsigned positive values. Some languages, such as C and C++, have no defined behaviour if negative values are used.)Script error: No such module "Footnotes".Script error: No such module "Check for unknown parameters".Script error: No such module "Unsubst".
  5. ↑ In Scheme 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.
  6. ↑ The Bits class from Haskell's Data.Bits module defines both shift taking a signed argument and shiftL/shiftR taking unsigned arguments. These are isomorphic; 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.
  7. ↑ The VHDL arithmetic left shift operator is unusual. Instead of filling the LSB of the result with zero, it copies the original LSB into the new LSB. While this is an exact mirror image of the arithmetic right shift, it is not the conventional definition of the operator, and is not equivalent to multiplication by a power of 2. In the VHDL 2008 standard this strange behavior was left unchanged (for backward compatibility) for argument types that do not have forced numeric interpretation (e.g., BIT_VECTOR) but 'SLA' for unsigned and signed argument types behaves in the expected way (i.e., rightmost positions are filled with zeros). VHDL's shift left logical (SLL) function does implement the aforementioned 'standard' arithmetic shift.
  8. ↑ The C standard was intended to not restrict the C language to either ones' complement or two's complement architectures. In cases where the behaviours of ones' complement and two's complement representations differ, such as this, the standard requires individual C compilers to document the behaviour of their target architectures. The documentation for GNU Compiler Collection (GCC), for example, documents its behaviour as employing sign-extension.Script error: No such module "Footnotes".Script error: No such module "Check for unknown parameters".

References

Cross-reference

<templatestyles src="Reflist/styles.css" />

  1. ↑ Script error: No such module "citation/CS1".
  2. ↑ Script error: No such module "citation/CS1".
  3. ↑ Script error: No such module "citation/CS1".
  4. ↑ Script error: No such module "citation/CS1".
  5. ↑ Script error: No such module "citation/CS1".
  6. ↑ Thomas R. Cain and Alan T. Sherman. "How to break Gifford's cipher". Section 8.1: "Sticky versus Non-Sticky Bit-shifting". Cryptologia. 1997.
  7. ↑ Script error: No such module "citation/CS1".

Script error: No such module "Check for unknown parameters".

Sources used

<templatestyles src="Citation/styles.css"/>Script error: No such module "template wrapper".

<templatestyles src="Refbegin/styles.css" />

  • Script error: No such module "citation/CS1".
  • Script error: No such module "Citation/CS1".
  • Script error: No such module "citation/CS1".
  • Script error: No such module "citation/CS1".
  • Script error: No such module "citation/CS1".
  • Script error: No such module "citation/CS1".
  • Script error: No such module "citation/CS1".